simplify and reorganize webpack config

上级 636aed1f
......@@ -13,7 +13,7 @@ const IS_PRODUCTION = process.env.NODE_ENV === 'production';
const IS_DEV_SERVER = process.argv.join(' ').indexOf('webpack-dev-server') !== -1;
const DEV_SERVER_HOST = process.env.DEV_SERVER_HOST || 'localhost';
const DEV_SERVER_PORT = parseInt(process.env.DEV_SERVER_PORT, 10) || 3808;
const DEV_SERVER_LIVERELOAD = process.env.DEV_SERVER_LIVERELOAD !== 'false';
const DEV_SERVER_LIVERELOAD = IS_DEV_SERVER && process.env.DEV_SERVER_LIVERELOAD !== 'false';
const WEBPACK_REPORT = process.env.WEBPACK_REPORT;
const NO_COMPRESSION = process.env.NO_COMPRESSION;
......@@ -62,7 +62,7 @@ function generateEntries() {
return Object.assign(manualEntries, autoEntries);
}
const config = {
module.exports = {
mode: IS_PRODUCTION ? 'production' : 'development',
context: path.join(ROOT_PATH, 'app/assets/javascripts'),
......@@ -77,36 +77,22 @@ const config = {
globalObject: 'this', // allow HMR and web workers to play nice
},
devtool: IS_PRODUCTION ? 'source-map' : 'cheap-module-eval-source-map',
optimization: {
nodeEnv: false,
runtimeChunk: 'single',
splitChunks: {
maxInitialRequests: 4,
cacheGroups: {
default: false,
common: () => ({
priority: 20,
name: 'main',
chunks: 'initial',
minChunks: autoEntriesCount * 0.9,
}),
vendors: {
priority: 10,
chunks: 'async',
test: /[\\/](node_modules|vendor[\\/]assets[\\/]javascripts)[\\/]/,
},
commons: {
chunks: 'all',
minChunks: 2,
reuseExistingChunk: true,
},
},
resolve: {
extensions: ['.js'],
alias: {
'~': path.join(ROOT_PATH, 'app/assets/javascripts'),
emojis: path.join(ROOT_PATH, 'fixtures/emojis'),
empty_states: path.join(ROOT_PATH, 'app/views/shared/empty_states'),
icons: path.join(ROOT_PATH, 'app/views/shared/icons'),
images: path.join(ROOT_PATH, 'app/assets/images'),
vendor: path.join(ROOT_PATH, 'vendor/assets/javascripts'),
vue$: 'vue/dist/vue.esm.js',
spec: path.join(ROOT_PATH, 'spec/javascripts'),
},
},
module: {
strictExportPresence: true,
rules: [
{
test: /\.js$/,
......@@ -177,9 +163,34 @@ const config = {
],
},
],
noParse: [/monaco-editor\/\w+\/vs\//],
strictExportPresence: true,
},
optimization: {
nodeEnv: false,
runtimeChunk: 'single',
splitChunks: {
maxInitialRequests: 4,
cacheGroups: {
default: false,
common: () => ({
priority: 20,
name: 'main',
chunks: 'initial',
minChunks: autoEntriesCount * 0.9,
}),
vendors: {
priority: 10,
chunks: 'async',
test: /[\\/](node_modules|vendor[\\/]assets[\\/]javascripts)[\\/]/,
},
commons: {
chunks: 'all',
minChunks: 2,
reuseExistingChunk: true,
},
},
},
},
plugins: [
......@@ -233,37 +244,52 @@ const config = {
},
},
]),
],
resolve: {
extensions: ['.js'],
alias: {
'~': path.join(ROOT_PATH, 'app/assets/javascripts'),
emojis: path.join(ROOT_PATH, 'fixtures/emojis'),
empty_states: path.join(ROOT_PATH, 'app/views/shared/empty_states'),
icons: path.join(ROOT_PATH, 'app/views/shared/icons'),
images: path.join(ROOT_PATH, 'app/assets/images'),
vendor: path.join(ROOT_PATH, 'vendor/assets/javascripts'),
vue$: 'vue/dist/vue.esm.js',
spec: path.join(ROOT_PATH, 'spec/javascripts'),
},
},
// compression can require a lot of compute time and is disabled in CI
IS_PRODUCTION && !NO_COMPRESSION && new CompressionPlugin(),
// sqljs requires fs
node: {
fs: 'empty',
},
};
// WatchForChangesPlugin
// TODO: publish this as a separate plugin
IS_DEV_SERVER && {
apply(compiler) {
compiler.hooks.emit.tapAsync('WatchForChangesPlugin', (compilation, callback) => {
const missingDeps = Array.from(compilation.missingDependencies);
const nodeModulesPath = path.join(ROOT_PATH, 'node_modules');
const hasMissingNodeModules = missingDeps.some(
file => file.indexOf(nodeModulesPath) !== -1
);
if (IS_PRODUCTION) {
// compression can require a lot of compute time and is disabled in CI
if (!NO_COMPRESSION) {
config.plugins.push(new CompressionPlugin());
}
}
// watch for changes to missing node_modules
if (hasMissingNodeModules) compilation.contextDependencies.add(nodeModulesPath);
// watch for changes to automatic entrypoints
watchAutoEntries.forEach(watchPath => compilation.contextDependencies.add(watchPath));
if (IS_DEV_SERVER) {
config.devServer = {
// report our auto-generated bundle count
console.log(
`${autoEntriesCount} entries from '/pages' automatically added to webpack output.`
);
callback();
});
},
},
// enable HMR only in webpack-dev-server
DEV_SERVER_LIVERELOAD && new webpack.HotModuleReplacementPlugin(),
// optionally generate webpack bundle analysis
WEBPACK_REPORT &&
new BundleAnalyzerPlugin({
analyzerMode: 'static',
generateStatsFile: true,
openAnalyzer: false,
reportFilename: path.join(ROOT_PATH, 'webpack-report/index.html'),
statsFilename: path.join(ROOT_PATH, 'webpack-report/stats.json'),
}),
].filter(Boolean),
devServer: {
host: DEV_SERVER_HOST,
port: DEV_SERVER_PORT,
disableHostCheck: true,
......@@ -271,46 +297,10 @@ if (IS_DEV_SERVER) {
stats: 'errors-only',
hot: DEV_SERVER_LIVERELOAD,
inline: DEV_SERVER_LIVERELOAD,
};
config.plugins.push({
apply(compiler) {
compiler.hooks.emit.tapAsync('WatchForChangesPlugin', (compilation, callback) => {
const missingDeps = Array.from(compilation.missingDependencies);
const nodeModulesPath = path.join(ROOT_PATH, 'node_modules');
const hasMissingNodeModules = missingDeps.some(
file => file.indexOf(nodeModulesPath) !== -1
);
// watch for changes to missing node_modules
if (hasMissingNodeModules) compilation.contextDependencies.add(nodeModulesPath);
// watch for changes to automatic entrypoints
watchAutoEntries.forEach(watchPath => compilation.contextDependencies.add(watchPath));
// report our auto-generated bundle count
console.log(
`${autoEntriesCount} entries from '/pages' automatically added to webpack output.`
);
callback();
});
},
});
if (DEV_SERVER_LIVERELOAD) {
config.plugins.push(new webpack.HotModuleReplacementPlugin());
}
}
},
if (WEBPACK_REPORT) {
config.plugins.push(
new BundleAnalyzerPlugin({
analyzerMode: 'static',
generateStatsFile: true,
openAnalyzer: false,
reportFilename: path.join(ROOT_PATH, 'webpack-report/index.html'),
statsFilename: path.join(ROOT_PATH, 'webpack-report/stats.json'),
})
);
}
devtool: IS_PRODUCTION ? 'source-map' : 'cheap-module-eval-source-map',
module.exports = config;
// sqljs requires fs
node: { fs: 'empty' },
};
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册