Narrow the file search
1 include & exclude
1) action
- Limit compilation range
2) useage
module: {
rules: [
{
test: /\.js$/,
use: ['babel-loader? cacheDirectory'],
include: path.resolve(__dirname, 'src'),
exclude: /node_modules/
}
]
}
Copy the code
‘babel-loader? cacheDirectory’
You can also speed up babel-loader by as much as 2x by using the cacheDirectory option. This will cache transformations to the filesystem.
QA
The command line warning
[BABEL] Note: The code generator has deoptimised the styling of “/Users/xxx/Documents/xxx/webpack_test/test3/node_modules/lodash/lodash.js” as it exceeds the max of “500KB”.
If you exclude the range, no error will be reported
2 resolve.modules
1) action
- Tell webpack what directories should be searched when resolving modules.
2) useage
resolve: {
modules: [path.resolve('node_modules'), path.resolve('lib')]}Copy the code
3) note
-
Absolute and relative paths can both be used, but be aware that they will behave a bit differently.
-
A relative path will be scanned similarly to how Node scans for node_modules, by looking through the current directory as well as it’s ancestors (i.e. ./node_modules, .. /node_modules, and on).
-
With an absolute path, it will only search in the given directory.
-
If you want to add a directory to search in that takes precedence over node_modules/:
modules: [path.resolve(__dirname, "src"), "node_modules"]
Copy the code
4) QA
Module not found: Error: Can’t resolve ‘ajax’ in ‘/Users/xxx/Documents/xxx/webpack_test/test3/src’
You can add properties to the array when you need to specify a module directory other than node_modules
3 resolve.mainFields
1) action
- The resolveto. MainFields in the Webpack configuration is used to configure which entry file to use for the third-party module.
Json file that describes the properties of the module. There are fields that describe where the entry file is located. Resolve-.mainfields configurates which field to use as the description of the entry file.
The reason there can be multiple field description entry files is because some modules can be used in multiple environments at the same time, requiring different code for different runtime environments. Take the Isomorphic-FETCH API, which is an implementation of Promise but can be used in both browsers and node.js environments.
2) useage
In order to reduce the search step, you can set it as few as possible while specifying the entry file description fields for third-party modules. Since most third-party modules use the main field to describe the location of the entry file, you can configure Webpack like this:
Module. exports = {resolve: {mainFields: [module.exports = {resolve: {mainFields: ['main'],}};Copy the code
4 resolve.alias
1) action
- Configuration items use aliases to map the original import path to a new import path
- This optimization affects the use of tree-shaking to remove invalid code
2) useage
alias: {
"bootstrap": "bootstrap/dist/css/bootstrap.css"
}
Copy the code
5 resolve.extensions
1) action
- When the import statement does not have a file suffix, Webpack will automatically try to ask if the file exists after the suffix
- The default extension is Extensions: [‘.js’, ‘.json’]
2) useage
3) note
- The list of suffixes is as small as possible
- The highest frequency goes forward
- Use suffixes whenever possible in export statements
6 module.noParse
1) action
- The module.noParse configuration allows Webpack to ignore recursive parsing of files that are not modular
2) useage
module: {
noParse: [/react\.min\.js/]
}
Copy the code
2) note
Omitted files should not contain modular statements such as import, require, define, etc
2 DLL
1 action
DLL files are called dynamic link libraries. In a dynamic link library, functions and data can be called to other modules
- Package the base module into a separate dynamically linked library
- When the module to be imported is in the dynamically connected library, the module cannot be repackaged and is retrieved from the dynamically connected library
2 usage
Define plugin –> Reference plugin (DllReferencePlugin)
This example uses jquery as an example
1) define the DLL
- Used to package out a dynamic link library
- It needs to be built separately
webpack.jquery.config.js
module.exports = {
entry: ["jquery"].output: {
filename: "vendor.js".path: path.resolve(__dirname, "dist"),
libraryTarget: 'var'.// The way of packing, hou
library: "vendor_lib_vendor"// Name of the DLL
},
plugins: [
new webpack.DllPlugin({
name: "vendor_lib_vendor"./ / define a DLL
path: path.resolve(__dirname, "dist/vendor-manifest.json")]}});Copy the code
Json scripts added to package.json
"dll": "webpack --config webpack.jquery.config.js --mode development"
Copy the code
After the above files are configured, when running NPM run DLL on the terminal, two files will be generated in the dist directory, respectively vendor.js and vendor-manifest.json. Vendor. js contains the code for the packaged jquery file, and vendor-manifest.json is used for the association. With the DLL defined, it’s time to apply the packaged DLL.
2) refer to DLL
DllPlugin is introduced into the webpack.config.js configuration file
plugins: [
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require("./dist/vendor-manifest.json")})],Copy the code
3) use the DLL
App.html is added at the bottom of app.html
<script src="./vendor.js"></script>
Copy the code
3 note
LibraryTarget and library
They are needed when using Webpack to build a library that can be imported and used by other modules.
- Output. libraryTarget configures how the library is exported.
- Output. library Configures the name of the exported library. They are usually used together.
Output. LibraryTarget is an enumeration of strings and supports the following configurations.
1) var (default)
A written library will be assigned via var to a variable named by the library.
If output. Library =’LibraryName’ is configured, output and use the following code:
// Webpack output code var LibraryName = lib_code; // Lib_code is a self-executing function that returns a value. // Use the library method libraryname.dosomething ();Copy the code
2) commonjs
The libraries you write will be exported through the CommonJS specification.
If output. Library =’LibraryName’ is configured, output and use the following code:
// exports of Webpack code ['LibraryName'] = lib_code; // use the library method require('library-name-in-npm') ['LibraryName'].doSomething(); // Library-name-in-npm is the name of the module when it is published to the NPM repository.Copy the code
3) commonjs2
The libraries you write will be exported through the CommonJS2 specification, and the output and use code is as follows:
// module. Exports = lib_code; // use the library method require('library-name-in-npm').doSomething();
Copy the code
CommonJS2 is similar to the CommonJS specification. The difference is that CommonJS can only export with exports. CommonJS2 adds module.exports to CommonJS. When output.libraryTarget is commonJs2, it makes no sense to configure output.library.
4) this
The written library will be assigned this to the name specified by the library, and the output and usage code will be as follows:
// Webpack output code this['LibraryName'] = lib_code; Use the method of library / / this. LibraryName. DoSomething ();Copy the code
5) window
The library will be assigned to the name specified by the library through the window, that is, the library will be mounted to the window, output and use the following code:
// Webpack output code window['LibraryName'] = lib_code; Use the method of library / / the window. The LibraryName. DoSomething ();Copy the code
6) global
The written library will be assigned to the name specified by the library via global, that is, the library will be mounted to global, output and use the following code:
// Webpack output code global['LibraryName'] = lib_code; / / the method of using a library global. LibraryName. DoSomething ();Copy the code
Three HappyPack
1 action
The HappyPack allows Webpack to split tasks into multiple sub-processes for concurrent execution, which then send the results to the main process.
2 usage
install
Since WebPack 4.0 has just been released, the responding plug-in has not been updated yet, but you can add a @next to install the upcoming release
npm i happypack@next -D
Copy the code
webpack.config.js
module: {
rules: [{test: /\.css$/.use: 'happypack/loader? id=css'.// Pass processing of.js files to HappyPack instance Babel
// The HappyPack is used to process a particular class of files
include: path.resolve('./src'),
exclude: /node_modules/
},
{
test: /\.js/.use: 'happypack/loader? id=babel'.include: path.resolve('./src'),
exclude: /node_modules/}},plugins: [
new HtmlWebPackPlugin({
template: './src/index.html'
}),
new HappyPack({
id: 'babel'.loaders: ['babel-loader']// The same configuration as in rules
}),
new HappyPack({
id: 'css'.loaders: ['style-loader'.'css-loader']// The same configuration as in rules}),]Copy the code
Four ParallelUglifyPlugin
1.action
- Serialized compression of JS files can be changed to enable parallel execution of multiple child processes
2 usage
insatll
npm install webpack-parallel-uglify-plugin -D
Copy the code
webpackage.config.js
new ParallelUglifyPlugin({
workerCount: os.cpus().length - 1.// Start several subprocesses to perform compression concurrently. The default is the number of CPU cores of the current running computer minus 1
uglifyJS: {
output: {
beautify: false.// No formatting is required
comments: true.// Do not reserve comments
},
compress: {
warnings: false.// No warning is printed when UglifyJs removes unused code
drop_console: true.// Delete all 'console' statements, compatible with Internet Explorer
collapse_vars: true.// Insert variables that are defined but used only once
reduce_vars: true.// Extract static values that occur multiple times but are not defined as variables to reference}}})Copy the code
5 The server automatically refreshes
1 File Listening
1) action
- You can listen for file changes and recompile when the file changes
2) useage
watch: true,
watchOptions: {
ignored: /node_modules/,
aggregateTimeout: 300,
poll: 1
}
Copy the code
3) note
watch
WatchOptions are only meaningful if the listening mode is enabled (watch is true)
aggregateTimeout
Listen for changes and wait 300(ms) before performing the action to prevent files from being updated too quickly and compiling too frequently
poll
Determine whether a file has changed by constantly asking if the file has changed. The default is 1000 times per second
File Listening Process
Webpack regularly gets the update time of the file and compares it to the last time it was saved. Inconsistency means a change has occurred, and poll is used to configure how many times to ask per second.
When detecting that the file does not change, the file is cached and then notified to the listener after a period of time. The waiting time is configured using aggregateTimeout.
Webpack will only listen to the files that the entry depends on. We need to minimize the number of files we need to listen to and the frequency of checking. Of course, lower frequency will result in lower sensitivity.
2 Refresh the browser automatically
1) use
devServer: {
inline: true
},
Copy the code
2) note
Webpack is responsible for listening for file changes, and webpack-dev-server is responsible for refreshing the browser. These files are packaged into the chunk, which initiates WebSocket connections to the server on behalf of clients
3 Hot replacement of modules
1) action
- Hot Module Replacement is a technology that updates only the specified Module without refreshing the entire web page.
- The principle is that when a source code changes, only the changed module is recompiled and the corresponding old module in the browser is replaced with the new output module
2) advantage
- Faster response, shorter time
- Do not refresh the page to keep the running state of the page
- Listen to fewer files
- Ignore the files in node_modules
2) use
webpack.config.js
devServer: {
hot:true// Set hot totrue} / / need plugins plugins: [new webpack. NamedModulesPlugin (), / / display module. The relative path of new webpack HotModuleReplacementPlugin () / / start heat load function]Copy the code
code
if (module.hot) {
module.hot.accept('./hot.js', () = > {let hot = require('./hot');
document.getElementById('app2').innerHTML = hot + '1'; })}Copy the code
3 note
Modules that require hot loading need to be introduced into the module during initialization, otherwise HMR will not be triggered.
Chapter VI Distinguishing the environment
1 action
In the development of web pages, there will be more than a set of running environment, for example, in the development process of convenient development and debugging environment. A runtime environment published online for use by users.
The differences between an online environment and a development environment are as follows:
- The code on the line is compressed
- The development environment may print a log that only the developer can see
- The back-end data interface may differ between a development environment and an online environment
2 usage
package.json
cross-env
Cross-platform setting environment variables (no && after)
"scripts": {
"build-dev": "cross-env NODE_ENV=development webpack --mode development"."build-prod": "cross-env NODE_ENV=production webpack --mode production"
}
Copy the code
webpack.config.js
- Distinguish between production and development environments based on environment variables, and then
webpack.base.config.js
Merge, and the production (or development) environment takes precedencewebpack.base.config.js
The configuration.
let merge = require('webpack-merge');
let base = require('./webpack.base.config');
let other = null;
if (process.env.NODE_ENV === 'development') {
other = require('./webpack.dev.config');
} else {
other = require('./webapack.prod.config');
}
module.exports = merge(base, other);
Copy the code
webpack.base.config.js
- The basic configuration
webpack.DefinePlugin
Defining environment variables
Basic configuration... plugins: [new webpack.DefinePlugin({
__isDevelopment__: JSON.stringify(process.env.NODE_ENV == 'development')})]Copy the code
webpack.dev.config.js
- In order to
output
For example, if the parameters of the development and production environments are different, overridewebpack.base.config.js
Inside the configuration
const path = require('path');
module.exports = {
output: {
path: path.resolve('./dist'),
filename: "[name].dev.[hash:2].js"}};Copy the code
webpack.prod.config.js
- (in
output
For instance)
const path = require('path');
module.exports = {
output: {
path: path.resolve('./dist'),
filename: "[name].prod.[hash:8].js"}};Copy the code
base.js
- In the configuration file
webpack.DefinePlugin
Defined variables (__isDevelopment__
) is available in both the entry file and other files referenced by the entry file__isDevelopment__
The value of the
let env = null;
if (__isDevelopment__) {
env = 'dev';
} else {
env = 'prod';
}
module.exports = env;
Copy the code
index.js
let env = require('./base.js');
if (__isDevelopment__) {
console.log('dev');
} else {
console.log('prod');
}
console.log('env', env);
/*
prod
env prod
*/
Copy the code
3 note
webpack.DefinePlugin
The reason for wrapping a string in json.stringify (‘production’) when defining the value of an environment variable is that the value of the environment variable needs to be a string wrapped in double quotes, and the value of json.stringify (‘production’) is exactly equal to ‘”production”‘.
Seven CDN
CDN is also called content delivery network. By deploying resources to all parts of the world, users can obtain resources from the nearest server according to the principle of proximity during access, thus accelerating resource acquisition speed.
- HTML file is not cached, put on your own server, turn off your server cache, static resource URL to the CDN server address
- For static JavaScript, CSS, and image files, CDN and cache are enabled, and the file names have HASH values
- Different static resources are allocated to different CDN servers so that parallel loading does not block
Eight Tree Shaking
1 action
Tree Shaking can be used to weed out dead code that is not useful in JavaScript.
2 useage
- It relies on static ES6 modularization syntax, such as importing and exporting via import and export
- Do not compile ES6 modules
use: {
loader: 'babel-loader'.query: {
presets: [["env", {
modules: false // Turn off Babel's module conversion and keep the original ES6 modularized syntax}]."react"]}},Copy the code
3 note
Note that it relies on static ES6 modularized syntax, such as importing and exporting via import and export. That is, Tree Shaking doesn’t make sense if your project code is running in an environment that doesn’t support ES6 syntax.
Extract common code
Why do I need to extract common code
Large sites have multiple pages, each with the same technology stack and style code, containing a lot of common code, which can be problematic if all of them are included
The same resources are repeatedly loaded, wasting user traffic and server costs; Too many resources are required to load each page. As a result, the first screen of the page is loaded slowly, affecting the user experience. If common code can be separated into separate files for loading, it can be optimized to reduce network traffic and reduce server costs
2 How to Extract
1) classification
Different types of files have different code blocks:
- Base class library, convenient long-term caching
- Common code between pages
- Each page generates a separate file
2) usage
webpack.config.js
Optimization: {splitChunks: {cacheGroups: {Commons: {// common code chunks between pages:'initial',
minChunks: 2,
maxInitialRequests: 5, // The default limitis too small to showcase the effect minSize: 0 // This is example is too small to create commons chunks }, vendor: {// base class library chunks:'initial'.test: /node_modules/,
name: "vendor",
priority: 10,
enforce: true}}}},Copy the code
./src/pageA.js
require('./utils/utility1.js');
require('./utils/utility2.js');
require('react');
Copy the code
./src/pageB.js
require('./utils/utility2.js');
require('./utils/utility3.js');
Copy the code
./src/pageC.js
require('./utils/utility2.js');
require('./utils/utility3.js');
Copy the code
utils/utility1.js
module.exports = 1;
Copy the code
utils/utility2.js
module.exports = 2;
Copy the code
utils/utility3.js
module.exports = 3;
Copy the code
The result of the package
The generated results of the above three codes are as follows:
Ten Scope Hoisting
1 action
In Webpack3, the following applies in the case of Scope reactometer, as a new application:
- Code volume is smaller because function declaration statements generate a lot of code
- The code has a smaller memory overhead at run time because fewer functions are created in scope
2 useage
package.json
"build": "webpack --display-optimization-bailout --mode development".Copy the code
webpack.config.js
plugins: [
new ModuleConcatenationPlugin()
],
Copy the code
./h.js
export default 'scope hoist'
Copy the code
./index.js
import str from './h.js'
console.log(str);
Copy the code
3 note
ES6 syntax must be used otherwise it will not work (the –display-optimization-bailout argument prompts)
Chapter XI Code separation
Code separation is one of the most compelling features of WebPack. This feature makes it possible to separate code into different bundles, which can then be loaded on demand or in parallel. There are three common methods of code separation:
- Entry starting point: Manually separate the code using the Entry configuration.
- Prevent duplication: Use splitChunks to de-duplicate and separate chunks.
- Dynamic import: Code is separated by inline function calls to modules.
Entry starting points and prevention of repetition have been mentioned above, so let’s focus on dynamic imports
1 action
When optimizing for on-demand loading of a single-page application, the following principles are generally applied:
- Divide web site functions into one chunk for each category
- For the first time to open the page needs to directly load the function, as soon as possible to show to the user
- Certain function points that rely on large amounts of code can be loaded on demand
- The segmented code needs to be loaded on demand
2 usage
- use
import(module)
The grammar of the - Import an asynchronous load module is an ES7 syntax
- Import is a natural breaking point in WebPack
document.getElementById('play').addEventListener('click'.function(){
import('./vedio.js').then(function(video){
let name = video.getName();
console.log(name);
});
});
Copy the code
Reference documentation
- Webpack official documentation
- Chinese version of webpack official document
- webpackGitHub