An opinionated, mostly framework-agnostic toolchain to package ES6 applications and libraries for the browser.
npm install systematic
The file structure expected for your application or library.
├── dist # what gets built│ ├── app.settings.js│ ├── bundle.js│ ├── bundle.js.map│ ├── translations.json│ ├── an_asset.png│ └── index.html|├── src # your code│ ├── some_module/| | ├── enums.js| | ├── index.js| | ├── index.spec.js| | └── models.js| |│ ├── utils.js│ ├── index.html # HTML entry point (applications)│ ├── index.spec.js # A test spec file│ └── index.js # JS entry point|├── webpack.config.js # Webpack config, inherits systematic's├── karma.config.js # Karma config, inherits systematic's├── Makefile # Your application's Makefile└── systematic.ini # systematic config
Systematic requires a
systematic.ini configuration file in the root folder of your project.
[build]; Mandatory; Project type, can be application, component or library. An app will need an HTML entry pointtype = library; Optional, default: vanilla; Build profile, can be angular, vue...profile = vanilla; Optional, default: dist; The relative path for the build output, defaults to distoutput_dir = dist; Optional, default: src; The relative path to the source dirsrc_dir = src; Optional, default: /; The path where the application will be hosted in production (eg. '/app/')public_path = /; Optional, default is blank; The locales to generate translation fileslocales = en_US en_GB; Optional, default is true; Whether to hash the generated bundle.js (relevant only for type = application)enableFileNameHashing = false[serve]; Interface to listenhost = 127.0.0.1; Optional, default: 8080; The network port to access local website, if it's an appport = 8080[test]; Optional, default: <YOUR_SRC_DIR>/**/*tests.js; All files matching this pattern will be processed with karma; It is relative to the root given to the karma config, usually the project rootfile_pattern = src/**/*tests.js
Systematic uses GNU
make. Create a Makefile at the root of your project, to import systematic commands:
include node_modules/systematic/mk/main.mk# Your own commands
The default source folder (containing your source code and tests) is
src. It must contain an entrypoint file named
// Bootstrap your project heresomelib
If your project is an application, there must be an HTML entry point named
index.html in the source folder, containing the primary page. Your JS entry point will be automatically added.
Your website<!-- Some application bootstrap !-->
make help gives a list of all commands.
make serve to run a local server.
make dist for a prod build.
make test runs all test that match the test file pattern (default
make livetest run test continuously, when a file changes.
make makemessages extract translations from your HTML and JS files using easygettext.
.po files will be in
make translations generates a JSON file from them, located at
dist/translations.json. It is automatically run with
You can then load them in your JS as an object:
make settings generates a file
dist/app.settings.js from all INI files in
src/settings/ if your project is an application.
Settings files are processed in alphabetical order, the last one overriding the previous. It is automatically run with
The generated file
dist/app.settings.js needs to be included in your index.html, since it will not be added by Webpack.
profile option. For now, only the
angular profile is supported on top of the
Adds the ng-annotate Babel plugin.
Adds translation management with the vue translation token.
It's possible to override the build or test config by adding config files at the root of the projet.
webpack.config.js. Example :
// import systematic default webpack settingsconst webpackDefaults =// optional overrides (an example !)webpackDefaultsmoduleloadersmoduleexports = webpackDefaults
// import systematic default karma settingsconst karmaDefaults =// optional overrides examplekarmaDefaultspluginsmodule karma
A component is halfway between a library and an application. You get to have an index.html page that is useful for development, but the dependencies aren't bundled with the final package, just like a library.
When building a library, we don't want the dependencies included in the bundle. It can cause version conflict with other packages or duplicated library imports.
Systematic will set all dependencies as webpack "externals", which means they have to be required by the app.
Systematic uses Babel to transpile ES6, ES6+ code to plain ES5. Polyfilling is then needed:
An example of what 1. means:
console.log('blah'.repeat(2)) // Dynamically dispatched so transpilation lets it untouched
Polyfilling actually consists in using a standard library.
Phantom JS with Babel
babel-polyfill (as it lacks 'Promises' for example).
If you build an app, you have two solutions:
babel-polyfilljust like in tests. You have to include it in the app entry point, before any other import:
babel-polyfillis built) on a per case basis:
;const myStr = ;
(1) has the advantage of simplicity and consistency across browsers but it pollutes the global scope and burdens your app. So (1) is advised as a first approach and (2) when you feel like it's time to make optimizations.
Avoid a global polyfill as it touches global variables. Use imports from
core-js as described above.
You should probably allow more watchers on your machine, see how on webpack's doc.