284 lines
13 KiB
JavaScript
284 lines
13 KiB
JavaScript
// Node imports
|
|
import path from 'path';
|
|
import process from "process";
|
|
import { exec } from "child_process";
|
|
|
|
// Rollup plugin imports
|
|
import less from 'rollup-plugin-less';
|
|
import sourcemaps from 'rollup-plugin-sourcemaps';
|
|
import stringLoader from "rollup-plugin-string";
|
|
import jsonPlugin from "rollup-plugin-json";
|
|
|
|
// Build/dev imports
|
|
import {Buildup, assetPlugin, babelPlugin, copyPlugin, handlebarsPlugin, minifyPlugin, commonJSPlugin} from "@cerxes/buildup";
|
|
|
|
// Util imports
|
|
import readArgs from "./util/read-args";
|
|
|
|
// Control
|
|
async function build(options) {
|
|
// Build
|
|
let error = false, result;
|
|
let watch = options.get("watch","w");
|
|
let development = options.get("dev", "d");
|
|
let server = options.get("server", "s");
|
|
let minify = options.get("minify", "m");
|
|
if(minify===undefined){minify = !development;}
|
|
|
|
try {
|
|
let settings = {
|
|
target: "web",
|
|
dev: development,
|
|
minify: minify,
|
|
es6: false //development
|
|
};
|
|
let builder = new Buildup(({meta: settings})=>({
|
|
outDir: "dist/" + settings.target,
|
|
inDir: "src",
|
|
clean: true,
|
|
alias: [
|
|
["common", "src/common"]
|
|
],
|
|
sourcemap: settings.dev?"inline":true, // 'inline' tends to work more reliably in chrome than just true (which is default and should be preferred)
|
|
plugins: [
|
|
// Import less as strings
|
|
less({// TODO fork/clone the less plugin, it's npm package is annoyingly transpiled (requiring us to have a babel-runtime) and it has other minor issues...
|
|
output: (args)=>args// This is how we avoid the .css file from being made, and it feels hacky
|
|
}),
|
|
// Resolve maps from node_modules
|
|
sourcemaps(),
|
|
// Resolve non-es6 node_module libraries
|
|
commonJSPlugin({
|
|
include: /node_modules\/.*$/,
|
|
exclude: /.*[\/\.]es6?[\/\.].*/
|
|
}),
|
|
],
|
|
|
|
steps: (config)=>[
|
|
[
|
|
{ // Site Build (www, targeting browsers)
|
|
inDir: "src/www",
|
|
outDir: config.outDir + (settings.outDir? "/"+settings.outDir : "")+"/www",
|
|
|
|
plugins: [
|
|
...config.plugins,
|
|
|
|
// Add ability to pass non-js files through the build-system
|
|
assetPlugin({
|
|
exclude: [/\.svg$/]
|
|
}),
|
|
// Load gcodes and svgs as strings
|
|
stringLoader({
|
|
include: ['**/*.gcode', '**/*.svg']
|
|
}),
|
|
// Transform source files with babel (uses src/.babelrc for configuration)
|
|
babelPlugin({
|
|
"target":"source"// transform the source inputs (could leave this undefined, its the default)
|
|
}),
|
|
// Transform output files with babel for browser compatibility
|
|
settings.es6? null : babelPlugin({
|
|
"target": "bundle", // only transform the output bundle, not the source inputs
|
|
"presets": [
|
|
[
|
|
"@babel/preset-env",
|
|
{
|
|
"targets": {
|
|
"browsers": [
|
|
"last 6 Chrome versions",
|
|
"last 1 Edge versions",
|
|
"last 2 Firefox versions",
|
|
]
|
|
},
|
|
"modules": false // Leave module processing to the custom transform-es-module plugin
|
|
}
|
|
]
|
|
],
|
|
"plugins": [
|
|
"@babel/plugin-syntax-dynamic-import",
|
|
"@cerxes/buildup/dist/babel-transform-es-modules"
|
|
],
|
|
}),
|
|
// Compress output
|
|
settings.minify? minifyPlugin() : null,
|
|
],
|
|
steps: (wwwConfig)=>[
|
|
// Serial compilation steps:
|
|
// - Compile vendor bundle first (needed/used in the next chunks)
|
|
[
|
|
{
|
|
// array in, single out
|
|
in: [
|
|
"@cerxes/cxs-ui",
|
|
],
|
|
out: "lib/vendor.js",
|
|
bundle:"flat",
|
|
},
|
|
],
|
|
|
|
// - Copy polyfills
|
|
Buildup.scanDir(
|
|
"node_modules/@webcomponents/webcomponentsjs/bundles/",
|
|
/(webcomponents-([\-a-zA-Z]+)\.js)$/
|
|
).then(wcPolyfills=>wcPolyfills.map(polyfill=>({
|
|
meta: polyfill,
|
|
in: polyfill.files,
|
|
out: "lib/polyfills/[1]",
|
|
plugins: [
|
|
copyPlugin()
|
|
]
|
|
}))),
|
|
|
|
// - Compile pages
|
|
Buildup.scanDir(
|
|
wwwConfig.resolveIn("pages"), // Scan directory src/pages for files
|
|
/(.*)\.page\.js$/ // (...) RegEx capture-group feeds into chunk-meta step allowing us to use [1]...[n] in strings below
|
|
).then(pages=>pages.map(page=>({
|
|
meta: page,
|
|
in: page.files,
|
|
out: "[1].page.js",
|
|
steps: (pageChunk)=>[
|
|
{
|
|
in: {
|
|
alias: "[1].polyfill-loader.virtual.js", // Passing in an alias within the src/ map will allow babel to find the appropriate .babelrc to transpile it
|
|
content: `import {loadPolyfills} from "pages/polyfill-loader"; loadPolyfills();`
|
|
},
|
|
out: "[1].loader.virtual.js",
|
|
emit: false,
|
|
steps: (polyloaderChunk)=>({
|
|
in: {
|
|
alias: "[1].loader.virtual.js", // Passing in an alias within the src/ map will allow babel to find the appropriate .babelrc to transpile it
|
|
content: `import {loadPage} from "pages/page-loader"; import(\`${"./" + path.basename(pageChunk.outPath)}\`).then(module=>loadPage(module));` // Loader-code
|
|
},
|
|
out: "[1].loader.virtual.js",
|
|
emit: false,
|
|
steps: (loaderChunk)=>[
|
|
{
|
|
// Feed the loader as input to html-generator
|
|
in: "page.hbs",
|
|
plugins: [handlebarsPlugin({
|
|
context: {
|
|
polyfill: polyloaderChunk.compiled.code,
|
|
pageCode: loaderChunk.compiled.code,
|
|
es6: settings.es6
|
|
}
|
|
})],
|
|
out: "[1].html"
|
|
}
|
|
]
|
|
})
|
|
}
|
|
]
|
|
}))),
|
|
|
|
// - Copy assets
|
|
Buildup.scanDir(
|
|
wwwConfig.resolveIn(""), // Scan directory src/pages for files
|
|
/(.*)\.(eot|svg|ttf|woff|png|jpg)$/ // (...) RegEx capture-group feeds into chunk-meta step allowing us to use [1]...[n] in strings below
|
|
).then(assets=>assets.map(asset=>({
|
|
meta: asset,
|
|
in: asset.files[0],
|
|
out: "[1].[2]",
|
|
asset: true
|
|
})))
|
|
]
|
|
}
|
|
],
|
|
[
|
|
{ // Server Build (targetting node-environment)
|
|
inDir: "src/server",
|
|
outDir: config.outDir + (settings.outDir? "/"+settings.outDir : ""),
|
|
|
|
plugins: [
|
|
jsonPlugin({
|
|
// for tree-shaking, properties will be declared as
|
|
// variables, using either `var` or `const`
|
|
preferConst: true, // Default: false
|
|
}),
|
|
...config.plugins,
|
|
// Transform source files with babel (uses src/.babelrc for configuration) for nodejs compatibility
|
|
babelPlugin({
|
|
"target":"source"// transform the source inputs (could leave this undefined, its the default)
|
|
}),
|
|
// Transform output files with babel for nodejs compatibility
|
|
babelPlugin({
|
|
"target": "bundle", // only transform the output bundle, not the source inputs
|
|
"presets": [
|
|
["@babel/preset-env", {
|
|
"targets": {
|
|
"node": "current"
|
|
},
|
|
}]
|
|
],
|
|
}),
|
|
// Compress output
|
|
settings.minify? minifyPlugin() : null,
|
|
],
|
|
|
|
nodeResolve: {
|
|
browser: false,
|
|
external: ({importee, importer, resolved, pkg})=> pkg.builtin||(pkg&&pkg.name==='mongodb')// Flag builtins as external
|
|
},
|
|
|
|
steps: (serverConfig)=>[
|
|
[
|
|
{
|
|
in: "main.js",
|
|
out: "main.js",
|
|
bundle:"flat",
|
|
},
|
|
],
|
|
]
|
|
}
|
|
],
|
|
]
|
|
}));
|
|
result = await builder.run(settings, {
|
|
watch: watch
|
|
}
|
|
);
|
|
}catch(err){
|
|
error = true;
|
|
console.error(err);
|
|
}
|
|
|
|
// Start server?
|
|
if(result&&server) {
|
|
console.log("Starting server...");
|
|
let started = exec("node \"./main.js\"",{
|
|
cwd: './dist/web'
|
|
});
|
|
|
|
started?.stdout.on('data', (data)=>{
|
|
console.log(data.toString());
|
|
});
|
|
|
|
started?.stderr.on('data', (data)=>{
|
|
console.error(data.toString());
|
|
});
|
|
}
|
|
|
|
if(watch) {
|
|
// If in watch/dev-server mode, enter this crappy infinite loop (TODO?)
|
|
let done = false;
|
|
let interval = 500;
|
|
while (!done) {
|
|
let msg = await new Promise((resolve) => setTimeout(() => resolve(error ? "KILL" : "TICK"), interval));
|
|
if (msg === "KILL") {
|
|
done = true;
|
|
}
|
|
}
|
|
}
|
|
return error;
|
|
}
|
|
|
|
// Start
|
|
try {
|
|
let args = process.argv.slice(2);
|
|
let options = readArgs(args);
|
|
build(options).catch(ex=>{
|
|
console.error(ex);
|
|
});
|
|
}catch(ex){
|
|
console.error(ex);
|
|
}
|