⏲ Time invest: 30 Minutes ––– 👩🎓 Level: Expert
A lot of web projects opt into authoring their source code in a different format than the one it is delivered and executed in. This might involve transformations such as bundling, minifying and transpiling. patternplate supports those setups just fine, let's see how.
We will …
>=6 (Install)gitWe are using Babel here as an example, mainly because it is the ubiquitous in the JavaScript ecosystem at the time of writing.
The principles described below apply to any build system emitting JavaScript (optionally HTML and CSS).
Open a terminal window and create a new project folder:
mkdir babel-patternplate
Initialize the project with a package.json file:
npm init # will ask you a bunch of questions
Install required Babel packages as development dependencies
npm install -D @babel/cli @babel/core @babel/preset-env
Create a .babelrc and configure Babel to use the env preset
// .babelrc
{
"presets": [
"@babel/preset-env"
]
}
Test your babel setup with a file containing new JavaScript features.
Copy the following into test.js
// test.js
async function main() {
console.log("Hello world");
}
main();
Then execute babel on it
yarn babel test.js
This should emit something like:
"use strict";
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } function _next(value) { step("next", value); } function _throw(err) { step("throw", err); } _next(); }); }; }
// test.js
function main() {
return _main.apply(this, arguments);
}
function _main() {
_main = _asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee() {
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
console.log("Hello world");
case 1:
case "end":
return _context.stop();
}
}
}, _callee, this);
}));
return _main.apply(this, arguments);
}
main();
Remove test.js
rm test.js
Create a src/ folder with some component sources in it:
mkdir -p src/button
cat > src/button/demo.js << EOF
module.exports = {
default: () => console.log("Button"),
html: () => \`<button>ES2015 Button</button>\`,
css: () => \`button {
padding: 10px 15px;
font-size: 20px;
background: none;
color: cornflowerblue;
border: 1px solid currentColor;
}\`
};
EOF
cat > src/button/pattern.json << EOF
{
"name": "button",
"version": "1.0.0"
}
EOF
Your src folder should look like this:
# TL;DR: commands above create a file tree like this
tree src
src
└── button
├── demo.js
└── pattern.json
1 directory, 2 files
Test drive Babel on src/:
⚠️ We use a Babel feature to copy non-JavaScript files from the src directory on change. This is not available in all systems (e.g. TypeScript).
Work around this by copying non-js files with
cpx, or enable source-maps in your compilation step.patternplateuses them to trace back to your sources if available.
# Build all js files from src to lib, copy non-js
babel src -D -d lib
The result in lib should look like this:
tree lib
lib
└── button
├── demo.js
└── pattern.json
1 directory, 2 files
Save your Babel command as run-script into package.json like this
{
"name": "babel-patternplate",
"version": "1.0.0",
"description": "A patternplate project with Babel as build system",
"scripts": {
"babel": "babel src -D -d lib "
},
"license": "MIT",
"devDependencies": {
"@babel/cli": "^7",
"@babel/core": "^7",
"@babel/preset-env": "^7"
}
}
That's it, we are set with a working build system. Thats pretty neat - this way we
can use features from the future of JavaScript, even in older runtimes!
Let's make the most of this and configure patternplate to pick up our transpiled code at lib/ next.
Install patternplate
npm install -D @patternplate/cli
Start patternplate
yarn patternplate
In a second terminal, start Babel in watch mode
yarn babel -w
Access your button component at http://localhost:1337/pattern/button.
If you used patternplate before this should be familiar:
Let's see if our Babel build plays nicely with patternplate's file system watchers.
Change the color of our Button to palevioletred:
module.exports = {
html: () => '<button class="my-button">ES2015 Button</button>',
css: () => `
.my-button {
padding: 10px 15px;
font-size: 20px;
background: none;
color: palevioletred;
border: 1px solid currentColor;
}',
`,
default: () => {
// Nothing implemented yet
}
}
The patternplate demo updates as soon as babel has built the changes from
src to lib:
patternplate works with all build systems that can emit JavaScript.
Configure your build to produce artifacts in lib and to pick them up with patternplate by default
The patternplate development watcher works with the results of e.g. the Babel watch mode.