The original link
Webpack4 Configuration overview
- Based on the react – boilerplate
- Technology stack ANTD + React + less
- Constantly updated
Front-end development
modular
Modularity refers to the decomposition of a complex system into modules for easy coding.
Mount to a variable
The jQuery library puts all its apis under window.$, and after loading jQuery, other modules can use jQuery through window.$
- Namespace conflicts. Two libraries may use the same name. For example, Zepto is also placed
window.$
Under; - Inability to properly manage project dependencies and releases;
- There is no easy way to control the loading order of dependencies.
CommonJS
Load dependent modules synchronously through the require method
/ / import
const moduleA = require('./moduleA');
/ / export
module.exports = moduleA.someFunc;
Copy the code
CommonJS benefits include:
- The code can be used in node.js environment and run, for example, do isomorphic applications;
- Many third-party modules released through NPM adopt the CommonJS specification.
The downside is that such code cannot run directly in a browser environment and must be converted to standard ES5 using tools.
AMD
Load dependent modules asynchronously
define('module'['dep'].function(dep) {
return exports;
});
// Import and use
require(['module'].function(module) {});Copy the code
The advantages of AMD are:
- Can run directly in the browser without converting code;
- Asynchronously loaded dependencies;
- Multiple dependencies can be loaded in parallel;
- The code can run in the browser environment and node.js environment.
The disadvantage of AMD is that the JavaScript runtime environment does not have native support for AMD. It needs to be imported into the AMD library before it can be used normally.
ES6 modular
Gradually replacing CommonJS and AMD specifications
/ / import
import { readFile } from 'fs';
import React from 'react';
/ / export
export function hello() {};
export default {
// ...
};
Copy the code
The downside is that it currently does not run directly in most JavaScript environments and must be converted to standard ES5 by tools.
Core WebPack concepts
The source code does not run directly and must be converted to run properly.
- Entry: Entry, the first step in the build that Webpack performs will start with Entry, which can be abstracted into input.
- Module: Module, in Webpack everything is a Module, a Module corresponds to a file. Webpack recursively finds all dependent modules starting from the configured Entry.
- Chunk: a Chunk is a code block. A Chunk is composed of multiple modules for code merging and splitting.
- Loader: module converter, used to convert the original content of a module into new content as required.
- Plugin: Extension Plugin that injects extension logic at specific points in the Webpack build process to change the build result or do what you want.
- Output: Outputs the result after Webpack has gone through a series of processes and produced the final desired code.
When Webpack starts, it recursively resolves all modules that Entry depends on, starting from the Module configured in the Entry. When a Module is found, the system finds the corresponding conversion rule based on the configured Loader, converts the Module, and resolves the Module dependent on the current Module. These modules are grouped by Entry, and an Entry and all its dependent modules are assigned to a group called a Chunk. Finally, Webpack converts all chunks into files for output. Webpack executes the logic defined in the Plugin at appropriate times throughout the process.
webpack.base.babel.js
/** * COMMON WEBPACK CONFIGURATION */
const path = require('path');
const webpack = require('webpack');
const fs = require('fs');
const lessToJs = require('less-vars-to-js');
const themer = lessToJs(
fs.readFileSync(path.join(__dirname, '.. /.. /app/antd-theme/theme.less'), 'utf8'));const postcssGlobalImport = require('postcss-global-import');
const postcssImport = require('postcss-import');
const postcssCustomProperties = require('postcss-custom-properties');
const postcssCustomMedia = require('postcss-custom-media');
const postcssMediaMinmax = require('postcss-media-minmax');
const postcssCustomSelectors = require('postcss-custom-selectors');
const postcssCalc = require('postcss-calc');
const postcssNesting = require('postcss-nesting');
const postcssNested = require('postcss-nested');
const postcssColorFunction = require('postcss-color-function');
const pleeeaseFilters = require('pleeease-filters');
const pixrem = require('pixrem');
const postcssSelectorMatches = require('postcss-selector-matches');
const postcssSelectorNot = require('postcss-selector-not');
const postcssFlexbugsFixes = require('postcss-flexbugs-fixes');
const autoprefixer = require('autoprefixer');
const globalJSON = require(path.resolve(process.cwd(), 'global.json'));
// Extract CSS into a separate file. It creates a CSS file for each JS file containing CSS. It supports on-demand loading of CSS and SourceMaps.
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const SimpleProgressWebpackPlugin = require('simple-progress-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = (options) = > ({
Resolve (__dirname, 'app') // Context: path.resolve(__dirname, 'app') // Context is the root directory, affecting the actual file pointed to by the relative path
entry: options.entry, // Mandatory, configure the module entry
mode: options.mode,
optimization: options.optimization,
output: Object.assign({ // Compile into js/build.js
// The configuration output file is stored in a local directory
path: path.resolve(process.cwd(), 'build'),
// The string URL prefix for all resources posted online
publicPath: '/',
}, options.output), // Merge with env dependent settings
module: { // Configure how to handle modules.
rules: [{test: /\.js$/.// Transform all .js files required somewhere with Babel
// Narrow the hit range as much as possible to speed up Webpack search
include: [/app/./unicorn/].// Exclude files in node_modules
// exclude: path.resolve(__dirname, 'node_modules'),
use: [
// The execution sequence of a group of Loaders is from right to left by default. Use Enforce to place the execution sequence of one Loader to the first or last.
// Multi-threaded loading time loader
'thread-loader',
{
loader: 'babel-loader'.options: options.babelQuery,
// Enforce :'post' means to place the execution order of the Loader at the end
// Enforce can also be pre, indicating that the execution order of the Loader is put first},],}, {test: /\.css/,
include: [/app/./unicorn/].use: [{// The CSS content is stored as strings in JavaScript
// Dynamically insert HTML style tags into the HTML head tag through DOM manipulation during JavaScript execution on the page.
If you want Webpack to output the CSS file separately, you might think that this will make the JavaScript file bigger and take longer to load the page
// WebPack4 uses mini-css-extract-plugin, previous versions use extract-text-webpack-plugin
loader: options.cssDebug ? 'style-loader' : MiniCssExtractPlugin.loader,
options: {
// Stylesheet Limits in Internet Explorer
// Maximum number of stylesheets and rules supported by Internet Explorer 6 through 9
// https://blogs.msdn.microsoft.com/ieinternals/2011/05/14/stylesheet-limits-in-internet-explorer/
singleton: false,}}, {loader: 'css-loader'.options: {
// CSS Loader https://github.com/webpack/css-loader
// Specify the maximum number of loaders that can pass through csS-loader before processing
// 0 => no loaders (default); 1 => postcss-loader; 2 => postcss-loader, sass-loader
importLoaders: 1.sourceMap: options.cssDebug,
// CSS Modules https://github.com/css-modules/css-modules
modules: true.localIdentName: options.cssDebug ? '[name]-[local]-[hash:base64:5]' : '[hash:base64:5]'.// CSS Nano http://cssnano.co/options/
// minimize: ! Options. cssDebug, // an error is reported in v2
// discardComments: {removeAll: true}, // v2 will report an error}, {},loader: 'postcss-loader'.options: {
plugins: [
// Transfer @global-import rule by inlining content with :global CSS Modules scope
// e.g. @global-import 'draft-js/dist/Draft.css'
// https://github.com/scherebedov/postcss-global-import
postcssGlobalImport(),
// Transfer @import rule by inlining content, e.g. @import 'normalize.css'
// https://github.com/postcss/postcss-import
postcssImport({ path: 'app' }),
// W3C variables, e.g. :root { --color: red; } div { background: var(--color); }
// https://github.com/postcss/postcss-custom-properties
postcssCustomProperties(),
// W3C CSS Custom Media Queries, e.g. @custom-media --small-viewport (max-width: 30em);
// https://github.com/postcss/postcss-custom-media
postcssCustomMedia(),
// CSS4 Media Queries, e.g. @media screen and (width >= 500px) and (width <= 1200px) { }
// https://github.com/postcss/postcss-media-minmax
postcssMediaMinmax(),
// W3C CSS Custom Selectors, e.g. @custom-selector :--heading h1, h2, h3, h4, h5, h6;
// https://github.com/postcss/postcss-custom-selectors
postcssCustomSelectors(),
// W3C calc() function, e.g. div { height: calc(100px - 2em); }
// https://github.com/postcss/postcss-calc
postcssCalc(),
// Allows you to nest one style rule inside another
// https://github.com/jonathantneal/postcss-nesting
postcssNesting(),
// Unwraps nested rules like how Sass does it
// https://github.com/postcss/postcss-nested
postcssNested(),
// W3C color() function, e.g. div { background: color(red alpha(90%)); }
// https://github.com/postcss/postcss-color-function
postcssColorFunction(),
// Convert CSS shorthand filters to SVG equivalent, e.g. .blur { filter: blur(4px); }
// https://github.com/iamvdo/pleeease-filters
pleeeaseFilters(),
// Generate pixel fallback for "rem" units, e.g. div {margin: 2.5rem 2px 3em 100%; }
// https://github.com/robwierzbowski/node-pixrem
pixrem(),
// W3C CSS Level4 :matches() pseudo class, e.g. p:matches(:first-child, .special) { }
// https://github.com/postcss/postcss-selector-matches
postcssSelectorMatches(),
// Transforms :not() W3C CSS Level 4 pseudo class to :not() CSS Level 3 selectors
// https://github.com/postcss/postcss-selector-not
postcssSelectorNot(),
// Postcss flexbox bug fixer
// https://github.com/luisrudge/postcss-flexbugs-fixes
postcssFlexbugsFixes(),
// Add vendor prefixes to CSS rules using values from caniuse.com
// https://github.com/postcss/autoprefixer
autoprefixer(/* package.json/browserslist */),],},},],}, {// custom Ant Design theme
test: /\.less$/,
include: /node_modules/,
use: [
{
loader: options.cssDebug ? 'style-loader' : MiniCssExtractPlugin.loader,
},
{
loader: 'css-loader'.// options: {
// minimize: true,
// },
},
{
loader: 'postcss-loader'.options: {
plugins: [autoprefixer()],
},
},
{
// Each Loader can pass in parameters either through the URL queryString or through options
// Can also specify in the source code which Loader to use to process files
// require('style-loader! css-loader? minimize! ./main.css');
// import '! file-loader? name=[name].[ext]! ./manifest.json';
loader: `less-loader? {"sourceMap":true,"modifyVars":The ${JSON.stringify(themer)}} `,},],}, {test: /\.css/,
include: /node_modules/,
use: [
{
loader: options.cssDebug ? 'style-loader' : MiniCssExtractPlugin.loader,
},
{
loader: 'css-loader'.options: {
importLoaders: 1.sourceMap: options.cssDebug,
// do not use css modules for original css in node_modules
// Importing third-party libraries does not hash them in case the styles do not take effect
// Enable the CSS module specification to automatically generate a hash value for each class that uniquely identifies the class
// :global does not convert its class name. The default is local
modules: false.// The format for generating the hash
localIdentName: options.cssDebug ? '[name]-[local]-[hash:base64:5]' : '[hash:base64:5]',},},],},// Temporarily block, affecting IE
/ / {
// test: /\.svg$/,
// use: [
/ / {
// loader: 'svg-url-loader',
// options: {
// // Inline files smaller than 10 kB
// limit: 10 * 1024,
// noquotes: true,
/ /},
/ /},
/ /,
// },
{
test: /\.(eot|ttf|woff|woff2|mp3|xls|xlsx|csv|mp4|webm|json|svg)$/,
use: [
{
loader: 'file-loader'.options: {
name() {
return '[name]-[hash].[ext]'; },},},],}, {test: /\.(jpe? g|png|gif)$/,
use: [
{
loader: 'url-loader'.options: {
// Inline files smaller than 10 kB
limit: 10 * 1024,}},/ / {
// loader: 'image-webpack-loader',
// options: {
// mozjpeg: {
// enabled: false,
// // NOTE: mozjpeg is disabled as it causes errors in some Linux environments
// // Try enabling it in your environment by switching the config to:
// // enabled: true,
// // progressive: true,
/ /},
// gifsicle: {
// interlaced: false,
/ /},
// optipng: {
// optimizationLevel: 7,
/ /},
// pngquant: {
// quality: '65-90',
// speed: 4,
/ /},
/ /},
// },],}, {test: /\.html$/,
use: 'html-loader'}, {test: /\.md$/,
use: [
{
loader: 'html-loader'}, {loader: 'markdown-loader'.options: {
gfm: true.tables: true.// highlight: (code) => highlight.highlightAuto(code).value,}},],}],// noParse: [// a module that does not need parsing and processing
// /special-library\.js$/ /
/ /,
},
// externals: {
// // Replace jquery in the import statement with the global jquery variable in the runtime
// jquery: 'jQuery'
// }
plugins: options.plugins.concat([ // Extend Webpack functionality so that Webpack can do almost anything related to a build
// new SimpleProgressWebpackPlugin(),
new webpack.ProvidePlugin({
// make fetch available, same as externals
fetch: 'exports-loader? self.fetch! whatwg-fetch'.$: 'jquery'.jQuery: 'jquery',}).// Always expose NODE_ENV to webpack, in order to use `process.env.NODE_ENV`
// inside your code for any environment checks; UglifyJS will automatically
// drop any unreachable code.
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(process.env.NODE_ENV),
GLOBAL: JSON.stringify(globalJSON || {}),
SERVER: JSON.stringify(process.env.SERVER),
},
}),
new CopyWebpackPlugin([
'app/favicon.ico'.'app/manifest.json',
].map((src) = > ({ from: src, to: path.resolve(process.cwd(), 'build')}))),new MiniCssExtractPlugin({
filename: '[name].[contenthash:8].css'.chunkFilename: '[name].[contenthash:8].css',}).// only load locale we need
// https://github.com/moment/moment/issues/2517#issuecomment-185836313
new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/./zh/), // eslint-disable-line
]),
resolve: { // How to configure Webpack to find the files corresponding to modules
// Configure Webpack to find third-party modules in directories. After configuration, you can simply import 'components', equivalent to import 'app/components'.
modules: ['app'.'node_modules'].// Map the original import path to a new import path by alias, $sign to narrow the scope to hit only the keyword ending
alias: {
// zh-cn.js will import '.. /moment', since we are using jsnext:main, it will pack two copys of moment.
moment$: path.resolve(process.cwd(), 'node_modules/moment/moment'),
unicorn: path.resolve(process.cwd(), 'unicorn'),
// Use alias to replace the react import statement with a single, complete react.production.min.js file to reduce time-consuming recursive parsing operations
// This method is generally used for libraries with strong integrity because it will affect tree-shaking removal of invalid code
// Libraries that do not apply to some utility classes, such as LoDash, result in output code containing a lot of code that will never be executed
react: path.resolve(process.cwd(), 'node_modules/react/cjs/react.production.min.js'),
'react-dom$': path.resolve(process.cwd(), 'node_modules/react-dom/cjs/react-dom.production.min.js'),
'react-dom/server$': path.resolve(process.cwd(), 'node_modules/react-dom/cjs/react-dom-server.browser.production.min.js'),},// When an import statement does not have a file suffix, Webpack automatically adds the suffix to try to access the file
extensions: [
// Minimize the possibility of trying suffixes
'.js'.// '.jsx',
// '.react.js',].// The package.json file will be searched in the order of the array, and only the first one found will be used
mainFields: [
// For third party modules in Npm, use ES6 modularity syntax files pointed out in jsNext :main.
// Enable Tree Shaking/Scope as of July 1
// Get rid of JavaScript dead code that doesn't work/make Webpack code smaller and faster, merge declarative code
'jsnext:main'.// 'browser',
'main'.// Use the main field as the description field of the entry file to reduce the search step],},devtool: options.devtool,
// Let Webpack build code for different runtime environments
target: 'web'.// Make web variables accessible to webpack, e.g. window
performance: options.performance || {},
// Output file performance check configuration
// performance: {
// Hints: 'warning', // Output a warning when there is a performance problem
// Hints: 'error', // Output errors with performance problems
// Hints: False, // Turn off performance checking
// maxAssetSize: 200000, // Maximum file size (bytes)
// maxEntrypointSize: 400000, // Maximum entry file size (bytes)
// assetFilter: function(assetFilename) {// Filter the file to check
// return assetFilename.endsWith('.css') || assetFilename.endsWith('.js');
/ /}
// },
});
Copy the code
webpack.dev.babel.js
/** * DEVELOPMENT WEBPACK CONFIGURATION */
const path = require('path');
const fs = require('fs');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CircularDependencyPlugin = require('circular-dependency-plugin');
const logger = require('.. /.. /server/logger');
const cheerio = require('cheerio');
const pkg = require(path.resolve(process.cwd(), 'package.json'));
const dllPlugin = pkg.dllPlugin;
const plugins = [
new webpack.HotModuleReplacementPlugin(), // Tell webpack we want hot reloading
new HtmlWebpackPlugin({
inject: true.// Inject all files that are generated by webpack, e.g. bundle.js
templateContent: templateContent(), // eslint-disable-line no-use-before-define
}),
new webpack.DefinePlugin({
__APP__: JSON.stringify({}),
}),
new CircularDependencyPlugin({
exclude: /a\.js|node_modules/.// exclude node_modules
failOnError: false.// show a warning when there is a circular dependency})];module.exports = require('./webpack.base.babel') ({mode: 'development'.// Add hot reloading in development
// If entry is a string or array, only one Chunk is generated, and the name of Chunk is main;
entry: [
'babel-polyfill'.'eventsource-polyfill'.// Necessary for hot reloading with IE
'webpack-hot-middleware/client? reload=true',
path.join(process.cwd(), 'app/app.js'), // Start with js/app.js].// Don't use hashes in dev mode for better performance
output: {
filename: '[name].js'.// Set the name of the output file. If there are multiple chunks to be exported, use [name].js
// Built-in variables include id, name, hash, and chunkhash
// The hash and chunkhash lengths are specified. [hash:8] indicates the 8-bit hash value. The default value is 20 bits.
// Note that the ExtractTextWebpackPlugin uses contenthash to represent hash values instead of chunkhash
// The reason is that the ExtractTextWebpackPlugin extracts the code content itself rather than chunks of a set of modules.
// Set the file name of Chunk without entry when exporting. This file name is used to specify the file name of Chunk generated during the run
// Generate Chunk scenarios using CommonChunkPlugin, dynamic loading using import('path/to/module'), etc.
// chunkFilename supports built-in variables consistent with filename
chunkFilename: '[name].chunk.js',},optimization: {
noEmitOnErrors: true.// Skip the error phase
splitChunks: {
chunks: 'all',}},// Add development plugins
plugins: dependencyHandlers().concat(plugins), // eslint-disable-line no-use-before-define
// Tell babel that we want to hot-reload
babelQuery: {
// require.resolve solves the issue of relative presets when dealing with
// locally linked packages. This is an issue with babel and webpack.
// See https://github.com/babel/babel-loader/issues/149 and
// https://github.com/webpack/webpack/issues/1866
presets: ['babel-preset-react-hmre'].map(require.resolve),
},
// Emit a source map for easier debugging
// Configure how Webpack generates the Source Map
// eval: wrap the module to be installed with an eval statement.
// source: generate a separate source Map file;
// Hidden: The JavaScript file indicates where the Source Map file is, so that the browser does not automatically load the Source Map;
// inline: Convert the generated Source Map to base64 inline JavaScript file;
// cheap: The generated Source Map does not contain column information, so that the calculation is less and the output Source Map file is smaller; The Source Map output by Loader will not be used.
// module: The Source Map from the Loader is simply processed as one module per line;
// Set devtool to cheap-module-eval-source-map in your development environment, since this source map is the fastest to generate and speeds up builds. Since code compression is not done in the development environment, breakpoint debugging is not affected even if there is no column information in the Source Map;
// Set devTool to hidden-source-map in production, which means generate the most detailed source map without exposing the Source map. Because code compression is done in a production environment, a JavaScript file is only one line long, so column information is required.
devtool: 'cheap-module-eval-source-map'.performance: {
hints: false,},cssDebug: true});/** * Select which plugins to use to optimize the bundle's handling of * third party dependencies. * * If there is a dllPlugin key on the project's package.json, the * Webpack DLL Plugin will be used. Otherwise the CommonsChunkPlugin * will be used. * */
function dependencyHandlers() {
// Don't do anything during the DLL Build step
if (process.env.BUILDING_DLL) { return []; }
// If the package.json does not have a dllPlugin property, use the CommonsChunkPlugin
if(! dllPlugin) {return [
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor'.children: true.minChunks: 2.async: true,})]; }const dllPath = path.resolve(process.cwd(), dllPlugin.path || 'node_modules/react-boilerplate-dlls');
/** * If DLLs aren't explicitly defined, we assume all production dependencies listed in package.json * Reminder: You need to exclude any server side dependencies by listing them in dllConfig.exclude */
if(! dllPlugin.dlls) {const manifestPath = path.resolve(dllPath, 'reactBoilerplateDeps.json');
if(! fs.existsSync(manifestPath)) { logger.error('The DLL manifest is missing. Please run `npm run build:dll`');
process.exit(0);
}
return [
new webpack.DllReferencePlugin({
context: process.cwd(),
// Describes the file contents of the dynamic link library
manifest: require(manifestPath), // eslint-disable-line global-require})]; }// If DLLs are explicitly defined, we automatically create a DLLReferencePlugin for each of them.
const dllManifests = Object.keys(dllPlugin.dlls).map((name) = > path.join(dllPath, ` /${name}.json`));
return dllManifests.map((manifestPath) = > {
if(! fs.existsSync(path)) {if(! fs.existsSync(manifestPath)) { logger.error(`The following Webpack DLL manifest is missing: ${path.basename(manifestPath)}`);
logger.error(`Expected to find it in ${dllPath}`);
logger.error('Please run: npm run build:dll');
process.exit(0); }}return new webpack.DllReferencePlugin({
context: process.cwd(),
manifest: require(manifestPath), // eslint-disable-line global-require
});
});
}
/** * We dynamically generate the HTML content in development so that the different * DLL Javascript files are loaded in script tags and available to our application. */
function templateContent() {
const html = fs.readFileSync(
path.resolve(process.cwd(), 'app/index.html')
).toString();
if(! dllPlugin) {return html; }
const doc = cheerio(html);
const body = doc.find('body');
constdllNames = ! dllPlugin.dlls ? ['reactBoilerplateDeps'] : Object.keys(dllPlugin.dlls);
dllNames.forEach((dllName) = > body.append(`<script data-dll='true' src='/${dllName}.dll.js'></script>`));
return doc.toString();
}
Copy the code
webpack.dll.babel.js
/** * WEBPACK DLL GENERATOR * * This profile is used to cache webpack's module * contexts for external library and framework type * dependencies which will usually not change often enough * to warrant building them from scratch every time we use * the webpack process. */
const { join } = require('path');
const defaults = require('lodash/defaultsDeep');
const webpack = require('webpack');
const pkg = require(join(process.cwd(), 'package.json'));
const dllPlugin = require('.. /config').dllPlugin;
if(! pkg.dllPlugin) { process.exit(0); }
const dllConfig = defaults(pkg.dllPlugin, dllPlugin.defaults);
const outputPath = join(process.cwd(), dllConfig.path);
module.exports = require('./webpack.base.babel') ({mode: 'development'.context: process.cwd(),
entry: dllConfig.dlls ? dllConfig.dlls : dllPlugin.entry(pkg),
devtool: 'eval'.output: {
filename: '[name].dll.js'.[name] indicates the name of the current dynamic link library
path: outputPath,
library: '[name]'.// Store the global variable name of the dynamic link library, for example, _dll_react
},
plugins: [
new webpack.DllPlugin({
// The global variable name of the dynamically linked library needs to be the same as that in output.library
// The value of this field is the value of the name field in the output [name]. Json file
// In webpack.dev.babel.js the DllReferencePlugin reads the name field from the [name].json file
// Use the contents of the value as the global variable name to retrieve the contents of the dynamically linked library from the global variable
name: '[name]'.// The name of the manifest.json file that describes the output of the dynamic link library
path: join(outputPath, '[name].json')}),// eslint-disable-line no-new].performance: {
hints: false,}});Copy the code
webpack.prod.babel.js
// Important modules this config uses
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const LodashModuleReplacementPlugin = require('lodash-webpack-plugin');
module.exports = require('./webpack.base.babel') ({mode: 'production'.// In production, we skip all hot-reloading stuff
// If entry is an object, there may be multiple chunks. In this case, the name of Chunk is the name of the key in the object key-value pair.
entry: {
main: ['babel-polyfill'.'raf/polyfill', path.join(process.cwd(), 'app/app.js')].draft: [
'draft-js'.'draft-js-plugins-editor'.'draft-js-mention-plugin'.'draft-convert',].'react-player': [
'react-player',]},babelOptions: {
// The babel-loader parameter is used to cache Babel compilation results to speed up recompilation
cacheDirectory: true,},// Utilize long-term caching by adding content hashes (not compilation hashes) to compiled assets
output: {
// Generate a file name based on the hash value of the file content for the browser to cache the file for a long time
filename: '[name].[chunkhash].js'.chunkFilename: '[name].[chunkhash].chunk.js',},optimization: {
minimize: true.minimizer: [
new UglifyJsPlugin({
cache: true.parallel: true.sourceMap: false.// A layer is nested
uglifyOptions: {
mangle: true.compress: {
// UglifyJs deletes unused code without warning
warnings: false.// Delete all 'console' statements, compatible with Internet Explorer
drop_console: true.// Inline variables that are defined but used only once
collapse_vars: true.// Extract static values that occur multiple times but are not defined as variables to reference
reduce_vars: true,},output: {
// Most compact output
beautify: false.// Delete all comments
comments: false,}}}),new OptimizeCSSAssetsPlugin(),
],
// Scope Hoisting
// Analyze the dependencies between modules and merge the separated modules into a function as much as possible, but only if there is no code redundancy.
// Therefore, only modules that have been referenced once can be merged.
concatenateModules: true.splitChunks: { // splitChunks and runtimeChunk replace commonsChunkPlugin in webPack1 ~3
// Set the home page of initial to 777K, jump to task center 204K
// Before upgrade, the home page is 739K, jump to task center 201K
// If the parameter is set to all, the home page is 1.1m and the task center is 18.7K
// chunks: 'initial', // As the name implies, async cuts chunks asynchronously loaded, initial for the initial chunk, and all for all chunks
// minSize: 30000, // The new chunk to be generated must be larger than 30KB. Otherwise, no new chunk is generated
// minChunks: 2, // Minimum number of chunks to share this module
// maxAsyncRequests: 2, // Up to five asynchronous load requests to the Module
// maxInitialRequests: 5, // The module is initialized with a maximum of four requests
// automaticNameDelimiter: '-', // The interval between the name
// Name: true, // The name of chunk. If set to true, the name is automatically generated based on the chunk to be extracted
// Optimization principle: to keep maximum reuse, the home page extracts all the public libraries of node_modules, resulting in long loading time
// The subsequent load is very fast
cacheGroups: {
default: false.// vendors: false,
draft: {
test: 'draft'.name: 'draft'.chunks: 'async'.priority: 3.// This configuration item sets the processing priority. A larger value indicates a higher processing priority
},
'react-player': {
test: 'react-player'.name: 'react-player'.chunks: 'async'.priority: 2.// This configuration item sets the processing priority. A larger value indicates a higher processing priority
},
vendors: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors'.chunks: 'all'.priority: 1.// This configuration item sets the processing priority. A larger value indicates a higher processing priority
},
common: {
name: 'common'.minChunks: 2.priority: -1.chunks: 'all'.reuseExistingChunk: true.// This configuration allows us to use existing code blocks
},
// polyfill: {
// test: 'polyfill', // This is used to decide which modules to extract. It can take strings, regular expressions, or functions. The function takes module as one argument and chunk as the second argument.
// name: 'polyfill',
// // reuseExistingChunk // Whether the previous chunk can be used if the module remains unchanged
// },
// vendor: {
// test: 'vendor',
// name: 'vendor',
// },
// styles: {
// name: 'styles',
// test: /\.css$/,
// chunks: 'all',
// },
// styles: {
// name: 'styles',
// test: /\.css$/,
// chunks: 'all',
// enforce: true,
// priority: 20,
// },}},runtimeChunk: {
name: 'manifest',}},plugins: [
new LodashModuleReplacementPlugin(), // LoDash is optimized from 592.53K to 240K
// Stabilize Chunkhash
new webpack.HashedModuleIdsPlugin(),
// Minify and optimize the index.html
new HtmlWebpackPlugin({
template: 'app/index.html'.minify: {
removeComments: true.collapseWhitespace: true.removeRedundantAttributes: true.useShortDoctype: true.removeEmptyAttributes: true.removeStyleLinkTypeAttributes: true.keepClosingSlash: true.minifyJS: true.minifyCSS: true.minifyURLs: true,},inject: true,})],performance: {
assetFilter: (assetFilename) = >! (/(\.map$)|(^(main\.|favicon\.) ) /.test(assetFilename)),
},
});
Copy the code
The above update is updated at 2019-2-13 19:47:27
Webpack configures global variables
Project background
Personalize the project title and icon. You can change the compiled file to achieve the effect of changing the title or icon without compiling
solution
This is mainly done by injecting global variables into the index.html file
Solving steps
- in
index.html
Inject global variables into
<script>
document.write("<s"+"cript type='text/javascript' src='/config.js?"+Math.random().toString(36).substr(2) +"'></scr"+"ipt>");
</script>
Copy the code
- in
app.js
To inject this file at compile timewebpack
Will copy files tobuild
directory
import '! file-loader? name=[name].[ext]! ./config.js';
Copy the code
Or add the following code to webpack.base.config.js to achieve the same effect
new CopyWebpackPlugin([
'app/config.js',
].map((src) = > ({ from: src, to: path.resolve(process.cwd(), 'build')}))),Copy the code
- in
config.js
Add global variables to
window.RUNTIME_CONSTANTS = {
title: "Baidu"};Copy the code
- Be happy with global variables