abtnode
Version:
Command line tools to manage ABT Node
133 lines (116 loc) • 3.99 kB
JavaScript
/* eslint-disable no-console */
const fs = require('fs');
const path = require('path');
const webpack = require('webpack');
const merge = require('webpack-merge');
// eslint-disable-next-line global-require
const debug = require('debug')(`${require('../package.json').name}:bundle`);
const testFilePattern = '\\.(test|spec)\\.?';
function findBabelConfig(blockletDir) {
const cwd = process.cwd();
return (
fs.existsSync(path.join(cwd, '.babelrc')) ||
blockletDir.split('/').some((dir) => {
const indexOf = blockletDir.indexOf(dir);
const dirToSearch = blockletDir.substr(0, indexOf);
return fs.existsSync(path.join(cwd, dirToSearch, '.babelrc'));
})
);
}
function getWebpackConfig({ userWebpackConfig, useBabelrc } = {}) {
const blockletDir = path.resolve(process.cwd());
// Blocklet config
const blockletConfig = path.join(blockletDir, 'blocklet.json');
if (!fs.existsSync(blockletConfig)) {
console.error('No blocklet.json found, which is required to bundle ABT Node blocklets');
process.exit(1);
}
let config = JSON.parse(fs.readFileSync(blockletConfig).toString());
const packageConfig = path.join(blockletDir, 'package.json');
if (fs.existsSync(packageConfig)) {
// eslint-disable-next-line prefer-object-spread
config = Object.assign({}, JSON.parse(fs.readFileSync(packageConfig).toString()), config);
}
debug({ blockletDir, blockletConfig, packageConfig, config });
if (!config.main || !fs.existsSync(path.join(blockletDir, config.main))) {
console.error('No main found in blocklet.json or package.json, which is required to bundle ABT Node blocklets');
process.exit(1);
}
// Babel config
const babelOpts = { cacheDirectory: true };
if (!findBabelConfig(blockletDir)) {
babelOpts.presets = [[require.resolve('@babel/preset-env'), { targets: { node: '10.15.1' } }]];
babelOpts.plugins = [
require.resolve('@babel/plugin-proposal-class-properties'),
require.resolve('@babel/plugin-transform-object-assign'),
require.resolve('@babel/plugin-proposal-object-rest-spread'),
];
}
// Webpack config
const env = process.env.NODE_ENV || 'development';
const mode = ['production', 'development'].includes(env) ? env : 'none';
const webpackConfig = {
mode,
resolve: {
extensions: ['.wasm', '.mjs', '.js', '.json', '.ts'],
mainFields: ['module', 'main'],
},
module: {
rules: [
{
test: /\.(m?js|ts)?$/,
exclude: new RegExp(`(node_modules|bower_components|${testFilePattern})`),
use: {
loader: require.resolve('babel-loader'),
options: { ...babelOpts, babelrc: useBabelrc },
},
},
],
},
context: blockletDir,
entry: {
// TODO: currently we only allow building 1 entry file
[path.basename(config.main, '.js')]: `./${config.main}`,
},
output: {
path: blockletDir,
filename: 'blocklet.js',
libraryTarget: 'commonjs',
},
target: 'node',
node: {
__dirname: false,
__filename: false,
},
plugins: [new webpack.IgnorePlugin(/vertx/), new webpack.DefinePlugin({})],
optimization: {
nodeEnv: env,
},
bail: true,
devtool: false,
stats: {
colors: true,
},
};
if (userWebpackConfig) {
// eslint-disable-next-line
const webpackAdditional = require(path.join(process.cwd(), userWebpackConfig));
return merge.smart(webpackConfig, webpackAdditional);
}
debug({ webpackConfig });
return webpackConfig;
}
exports.run = (additionalConfig) =>
new Promise((resolve, reject) => {
webpack(getWebpackConfig(additionalConfig), (err, stats) => {
if (err) {
reject(err);
} else {
resolve(stats);
}
});
});
exports.watch = (additionalConfig, cb) => {
const compiler = webpack(getWebpackConfig(additionalConfig));
compiler.watch(getWebpackConfig(additionalConfig), cb);
};