diff --git a/webpack/build.js b/webpack/build.js index bff9b505..938162f4 100644 --- a/webpack/build.js +++ b/webpack/build.js @@ -1,19 +1,30 @@ const webpack = require('webpack'); -const getWebpackConfig = require('./config'); +const { getConfig, getElectronMainConfig } = require('./config'); module.exports = function build(mode) { - const webpackConfig = getWebpackConfig(); + const rendererConfig = getConfig(); + const mainConfig = getElectronMainConfig(); + process.env.NODE_ENV = 'production'; if (mode === 'electron') { - pack(webpackConfig) + pack(rendererConfig) .then(result => { console.log(result); }).catch(err => { console.log(`\n Failed to build renderer process`); console.error(`\n${err}\n`); process.exit(1) - }) + }); + + pack(mainConfig) + .then(result => { + console.log(result); + }).catch(err => { + console.log(`\n Failed to build main process`); + console.error(`\n${err}\n`); + process.exit(1) + }); } } diff --git a/webpack/config.js b/webpack/config.js index 114c5951..858b5503 100644 --- a/webpack/config.js +++ b/webpack/config.js @@ -1,21 +1,19 @@ const webpack = require('webpack'); + +// plugins +const VueLoaderPlugin = require('vue-loader/lib/plugin'); +const HtmlWebpackPlugin = require('html-webpack-plugin'); +const CaseSensitivePathsWebpackPlugin = require('case-sensitive-paths-webpack-plugin'); +const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin'); +const CopyWebpackPlugin = require('copy-webpack-plugin'); + const { getAppConfig, resolveAppDir } = require('./utils'); const appDependencies = require(resolveAppDir('./package.json')).dependencies; const frappeDependencies = require('../package.json').dependencies; -function getConfig() { - const plugins = { - NamedModules: webpack.NamedModulesPlugin, - HotModuleReplacement: webpack.HotModuleReplacementPlugin, - Define: webpack.DefinePlugin, - Progress: webpack.ProgressPlugin, - VueLoader: require('vue-loader/lib/plugin'), - Html: require('html-webpack-plugin'), - CaseSensitivePaths: require('case-sensitive-paths-webpack-plugin'), - FriendlyErrors: require('friendly-errors-webpack-plugin'), - CopyWebpackPlugin: require('copy-webpack-plugin') - } +let getConfig, getElectronMainConfig; +function makeConfig() { const appConfig = getAppConfig(); const isProduction = process.env.NODE_ENV === 'production'; const isElectron = process.env.ELECTRON === 'true'; @@ -23,133 +21,182 @@ function getConfig() { const whiteListedModules = ['vue']; const allDependencies = Object.assign(frappeDependencies, appDependencies); - const externals = Object.keys(allDependencies).filter(d => !whiteListedModules.includes(d)) + const externals = Object.keys(allDependencies).filter(d => !whiteListedModules.includes(d)); - const config = { - mode: isProduction ? 'production' : 'development', - context: resolveAppDir(), - entry: isElectron ? appConfig.electron.entry : appConfig.dev.entry, - externals: isElectron ? externals : null, - target: isElectron ? 'electron-renderer' : 'web', - output: { - path: isElectron ? resolveAppDir('./dist/electron') : resolveAppDir('./dist'), - filename: '[name].js', - // publicPath: appConfig.dev.assetsPublicPath, - libraryTarget: isElectron ? 'commonjs2' : null - }, - devtool: !isProduction ? 'cheap-module-eval-source-map' : '', - module: { - rules: [ - { - test: /\.vue$/, - loader: 'vue-loader' - }, - { - test: /\.js$/, - loader: 'babel-loader', - exclude: file => ( - /node_modules/.test(file) && - !/\.vue\.js/.test(file) - ) - }, - { - test: /\.node$/, - use: 'node-loader' - }, - { - test: /\.css$/, - use: [ - 'vue-style-loader', - 'css-loader' - ] - }, - { - test: /\.scss$/, - use: [ - 'vue-style-loader', - 'css-loader', - 'sass-loader' - ] - }, - { - test: /\.(png|svg|jpg|gif)$/, - use: [ - 'file-loader' - ] + getConfig = function getConfig() { + const config = { + mode: isProduction ? 'production' : 'development', + context: resolveAppDir(), + entry: isElectron ? appConfig.electron.entry : appConfig.dev.entry, + externals: isElectron ? externals : null, + target: isElectron ? 'electron-renderer' : 'web', + output: { + path: isElectron ? resolveAppDir('./dist/electron') : resolveAppDir('./dist'), + filename: '[name].js', + // publicPath: appConfig.dev.assetsPublicPath, + libraryTarget: isElectron ? 'commonjs2' : null + }, + devtool: !isProduction ? 'cheap-module-eval-source-map' : '', + module: { + rules: [ + { + test: /\.vue$/, + loader: 'vue-loader' + }, + { + test: /\.js$/, + loader: 'babel-loader', + exclude: file => ( + /node_modules/.test(file) && + !/\.vue\.js/.test(file) + ) + }, + { + test: /\.node$/, + use: 'node-loader' + }, + { + test: /\.css$/, + use: [ + 'vue-style-loader', + 'css-loader' + ] + }, + { + test: /\.scss$/, + use: [ + 'vue-style-loader', + 'css-loader', + 'sass-loader' + ] + }, + { + test: /\.(png|svg|jpg|gif)$/, + use: [ + 'file-loader' + ] + } + ] + }, + resolve: { + extensions: ['.js', '.vue', '.json', '.css', '.node'], + alias: { + 'vue$': 'vue/dist/vue.esm.js', + 'deepmerge$': 'deepmerge/dist/umd.js', + '@': appConfig.dev.srcDir ? resolveAppDir(appConfig.dev.srcDir) : null } - ] - }, - resolve: { - extensions: ['.js', '.vue', '.json', '.css', '.node'], - alias: { - 'vue$': 'vue/dist/vue.esm.js', - 'deepmerge$': 'deepmerge/dist/umd.js', - '@': appConfig.dev.srcDir ? resolveAppDir(appConfig.dev.srcDir) : null + }, + plugins: [ + new webpack.DefinePlugin(Object.assign({ + 'process.env': appConfig.dev.env, + 'process.env.NODE_ENV': isProduction ? '"production"' : '"development"', + }, !isProduction ? { + '__static': `"${resolveAppDir(appConfig.staticPath).replace(/\\/g, '\\\\')}"` + } : {})), + new VueLoaderPlugin(), + new HtmlWebpackPlugin({ + template: resolveAppDir(appConfig.dev.entryHtml), + nodeModules: !isProduction + ? isMonoRepo ? resolveAppDir('../../node_modules') : resolveAppDir('./node_modules') + : false + }), + new CaseSensitivePathsWebpackPlugin(), + new webpack.NamedModulesPlugin(), + new webpack.HotModuleReplacementPlugin(), + new FriendlyErrorsWebpackPlugin({ + compilationSuccessInfo: { + messages: [`FrappeJS server started at http://${appConfig.dev.devServerHost}:${appConfig.dev.devServerPort}`], + }, + }), + new webpack.ProgressPlugin(), + isProduction ? new CopyWebpackPlugin([ + { + from: resolveAppDir(appConfig.staticPath), + to: resolveAppDir('./dist/electron/static'), + ignore: ['.*'] + }, + { + from: resolveAppDir(appConfig.electron.paths.main), + to: resolveAppDir('./dist/electron/main.js') + } + ]) : null, + // isProduction ? new BabiliWebpackPlugin() : null, + // isProduction ? new webpack.LoaderOptionsPlugin({ minimize: true }) : null, + ], + optimization: { + noEmitOnErrors: false + }, + devServer: { + // contentBase: './dist', // dist path is directly configured in express + hot: true, + quiet: true + }, + node: { + // prevent webpack from injecting useless setImmediate polyfill because Vue + // source contains it (although only uses it if it's native). + setImmediate: false, + // process is injected via DefinePlugin, although some 3rd party + // libraries may require a mock to work properly (#934) + process: 'mock', + // prevent webpack from injecting mocks to Node native modules + // that does not make sense for the client + dgram: 'empty', + fs: 'empty', + net: 'empty', + tls: 'empty', + child_process: 'empty' } - }, - plugins: [ - new plugins.Define(Object.assign({ - 'process.env': appConfig.dev.env, - 'process.env.NODE_ENV': isProduction ? '"production"' : '"development"', - }, !isProduction ? { - '__static': `"${resolveAppDir(appConfig.staticPath).replace(/\\/g, '\\\\')}"` - } : {})), - new plugins.VueLoader(), - new plugins.Html({ - template: resolveAppDir(appConfig.dev.entryHtml), - nodeModules: !isProduction - ? isMonoRepo ? resolveAppDir('../../node_modules') : resolveAppDir('./node_modules') - : false - }), - new plugins.CaseSensitivePaths(), - new plugins.NamedModules(), - new plugins.HotModuleReplacement(), - new plugins.FriendlyErrors({ - compilationSuccessInfo: { - messages: [`FrappeJS server started at http://${appConfig.dev.devServerHost}:${appConfig.dev.devServerPort}`], - }, - }), - new plugins.Progress(), - isProduction ? new plugins.CopyWebpackPlugin([ - { - from: resolveAppDir(appConfig.staticPath), - to: resolveAppDir('./dist/electron/static'), - ignore: ['.*'] - }, - { - from: resolveAppDir(appConfig.electron.paths.main), - to: resolveAppDir('./dist/electron/main.js') - } - ]) : null, - // isProduction ? new BabiliWebpackPlugin() : null, - // isProduction ? new webpack.LoaderOptionsPlugin({ minimize: true }) : null, - ], - optimization: { - noEmitOnErrors: false - }, - devServer: { - // contentBase: './dist', // dist path is directly configured in express - hot: true, - quiet: true - }, - node: { - // prevent webpack from injecting useless setImmediate polyfill because Vue - // source contains it (although only uses it if it's native). - setImmediate: false, - // process is injected via DefinePlugin, although some 3rd party - // libraries may require a mock to work properly (#934) - process: 'mock', - // prevent webpack from injecting mocks to Node native modules - // that does not make sense for the client - dgram: 'empty', - fs: 'empty', - net: 'empty', - tls: 'empty', - child_process: 'empty' } + + return config; } - return config; + getElectronMainConfig = function getElectronMainConfig() { + return { + entry: { + main: resolveAppDir(appConfig.electron.paths.main) + }, + externals: externals, + module: { + rules: [ + { + test: /\.js$/, + use: 'babel-loader', + exclude: /node_modules/ + }, + { + test: /\.node$/, + use: 'node-loader' + } + ] + }, + node: { + __dirname: !isProduction, + __filename: !isProduction + }, + output: { + filename: '[name].js', + libraryTarget: 'commonjs2', + path: resolveAppDir('./dist/electron') + }, + plugins: [ + new webpack.NoEmitOnErrorsPlugin(), + // isProduction && new BabiliWebpackPlugin(), + isProduction && new webpack.DefinePlugin({ + 'process.env.NODE_ENV': '"production"' + }) + ], + resolve: { + extensions: ['.js', '.json', '.node'] + }, + target: 'electron-main' + } + } } -module.exports = getConfig; +makeConfig(); + +module.exports = { + getConfig, + getElectronMainConfig +}; diff --git a/webpack/serve.js b/webpack/serve.js index c1f59c66..7f36da0b 100644 --- a/webpack/serve.js +++ b/webpack/serve.js @@ -5,7 +5,7 @@ const webpackHotMiddleware = require('webpack-hot-middleware'); const logger = require('./logger'); const { getAppConfig, resolveAppDir } = require('./utils'); -const getWebpackConfig = require('./config'); +const { getConfig: getWebpackConfig } = require('./config'); const log = logger('serve'); const warn = logger('serve', 'red');