const async = require('async'); const webpack = require('webpack'); const utils = require('../utils/utils'); const fs = require('../core/fs'); const constants = require('../constants'); // Override process.chdir so that we have a partial-implementation PWD for Windows const realChdir = process.chdir; process.chdir = (...args) => { if (!process.env.PWD) { process.env.PWD = process.cwd(); } realChdir(...args); }; let webpackProcess; class WebpackProcess { constructor(_options) { this.interceptLogs(); } interceptLogs() { const context = {}; context.console = console; context.console.log = this.log.bind(this, 'log'); context.console.warn = this.log.bind(this, 'warn'); context.console.info = this.log.bind(this, 'info'); context.console.debug = this.log.bind(this, 'debug'); context.console.trace = this.log.bind(this, 'trace'); context.console.dir = this.log.bind(this, 'dir'); } log(type, ...messages) { process.send({result: constants.pipeline.log, message: messages, type}); } build(file, importsList, callback) { const self = this; let realCwd; async.waterfall([ function findImports(next) { self.webpackRun(file.filename, {}, false, importsList, false, next); }, function changeCwd(next) { realCwd = utils.pwd(); process.chdir(fs.embarkPath('')); next(); }, function runWebpack(next) { self.webpackRun(file.filename, {}, true, importsList, true, next); }, function changeCwdBack(next) { process.chdir(realCwd); next(); } ], (err) => { process.chdir(realCwd); callback(err); }); } webpackRun(filename, options, includeModules, importsList, detectErrors, callback) { let defaultOptions = { entry: fs.dappPath(filename), output: { libraryTarget: 'umd', path: fs.dappPath('.embark'), filename: filename }, resolve: { alias: importsList, modules: [ fs.embarkPath('node_modules'), fs.dappPath('node_modules') ] }, externals: function (context, request, callback) { callback(); } }; let webpackOptions = utils.recursiveMerge(defaultOptions, options); if (includeModules) { webpackOptions.module = { rules: [ { test: /\.css$/, use: [{loader: "style-loader"}, {loader: "css-loader"}] }, { test: /\.scss$/, use: [{loader: "style-loader"}, {loader: "css-loader"}] }, { test: /\.(png|woff|woff2|eot|ttf|svg)$/, loader: 'url-loader?limit=100000' }, { test: /\.js$/, loader: "babel-loader", exclude: /(node_modules|bower_components)/, options: { presets: ['babel-preset-es2016', 'babel-preset-es2017', 'babel-preset-react'].map(require.resolve), plugins: ["babel-plugin-webpack-aliases"].map(require.resolve), compact: false } } ] }; } webpack(webpackOptions).run((err, stats) => { if (err) { console.error(err); } if (!detectErrors) { return callback(); } if (stats.hasErrors()) { return callback(stats.toJson().errors.join("\n")); } callback(); }); } } process.on('message', (msg) => { if (msg.action === constants.pipeline.init) { webpackProcess = new WebpackProcess(msg.options); return process.send({result: constants.pipeline.initiated}); } if (msg.action === constants.pipeline.build) { return webpackProcess.build(msg.file, msg.importsList, (err) => { process.send({result: constants.pipeline.built, error: err}); }); } }); process.on('exit', () => { process.exit(0); });