There are many build tools, such as Npm Script task executor, Grunt also Task executor, Gulp stream-based automated build tool, Fis3 Baidu Build tool, Webpack Modular JavaScript tool, and Rollup module package tool.
Here’s a look at the webPack build tool that’s used a lot.
The basic concept
Start with the basics:
The entrance (entry)
Entry is the entry of the configuration module. It is mandatory.
module.exports = {
entry: './path/to/my/entry/file.js'
}
Copy the code
Exports (output)
Output configures how to output the final desired code. Output is an object that contains a list of configuration items.
Filename Specifies the name of the configuration output file. The value is a string.
Output. path Specifies the local directory (path) where the output file is stored. The path must be an absolute string path.
path: path.resolve(__dirname, 'dist_[hash]')
Copy the code
Output. publicPath Configures the URL prefix published to online resources, which is of string type. The default is an empty string ”, that is, relative paths are used.
For example, the built resources need to be uploaded to the CDN service to speed up the opening of web pages. The configuration code is as follows:
filename: '[name]_[chunkhash:8].js'
publicPath: 'https://cdn.example.com/assets/'
Copy the code
When published online, the JavaScript files introduced in HTML are as follows:
<script src='https://cdn.example.com/assets/a_12345678.js'></script>
Copy the code
If a 404 error occurs on the line, check to see if the path is correct ~
See the documentation for other configurations
Module (module)
Module Configures how to handle modules.
Module. rules Configures the reading and parsing rules of modules, which are usually used to configure loaders. The type is an array, and each item in the array describes how to process part of the file. A rule may be applied in the following manner:
- Conditional match: Yes
test
,include
,exclude
Three configuration items are matchedLoader
The file to apply the rules to. - Application rule: Pass the selected file
use
Configure items to applyLoader
, you can only apply oneLoader
Or you can apply a set from back to frontLoader
And you can also giveLoader
Pass in parameters. - Reset order: one set
Loader
The execution sequence is from right to left by defaultenforce
The option is to make one of themLoader
The order of execution is first or last.
module: {
rules: [{// Hit the SCSS file
test: /\.scss$/.// Process from right to left
use: ['style-loader'.'css-loader'.'sass-loader'].// Exclude files in node_modules
exclude: path.resolve(__dirname, 'node_modules'),}}]Copy the code
An example of when a Loader needs to pass multiple arguments:
use: [
{
loader:'babel-loader'.options: {cacheDirectory:true,},// 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
enforce:'post'
},
// omit other loaders
]
Copy the code
The module.noParse configuration item helps build performance by allowing WebPack to ignore recursive parsing and processing of files that are not modularized. Such as:
module: {
noParse: (content) = > /jquery|lodash/.test(content)
}
Copy the code
The module.rules.parser attribute provides a more fine-grained configuration of which modules are parsed and which are not. The difference with noParse is that parser is syntactical and noParse only controls which files are not parsed.
module: {
rules: [{test: /\.js$/.use: ['babel-loader'].parser: {
amd: false./ / disable AMD
commonjs: false./ / disable CommonJS. }}}]Copy the code
Resolution (resolve)
Resolve configures how WebPack finds files for modules. Webpack built-in Javascript modular syntax parsing function, the default will use the modular standard inside the agreed rules to find, you can also modify the default rules as required.
The resolve.alias configuration item maps the original import path to a new import path through an alias. As follows:
resolve: {
alias: {
components: './src/components/'}}Copy the code
When you import Button from ‘components/ Button ‘, you are effectively replaced by alias import Button from ‘./ SRC /components/ Button ‘.
Resolve. modules configures the directory in which webpack finds third-party modules, and by default only node_modules is used.
When enforceExtension is set to true, all import statements must have a suffix, such as import ‘./foo working properly before enforceExtension, when it is enabled it must be written as import ‘./foo.js’.
Plug-in (plugins)
Plugins are used to extend Webpack functionality, and a variety of plugins allow Webpack to do almost anything build-related.
Here’s an example:
const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
module.exports = {
plugins: [
// The common code used by all pages is extracted into the common code block
new CommonsChunkPlugin({
name: 'common'.chunks: ['a'.'b']]}})Copy the code
DevServer configuration
Use it while developing your environment. To configure DevServer, you can pass in command-line parameters as well as DevServer parameters in the configuration file.
Note: DevServer in the configuration file only takes effect when Webpack is started via DevServer.
Devserver. hot Specifies whether to enable hot replacement of modules mentioned in devServer.
The devServer.host configuration item configures the IP address listened by the devServer service.
Devserver. port Configures the port monitored by devServer. By default, port 8080 is used.
Devserver. HTTPS Configures the HTTPS service. In some cases you must use HTTPS, HTTP2 and the Service Worker must run on HTTPS.
devServer: {
https: true
}
Copy the code
Webpack principle
Running Webpack is a sequential process, from start to finish:
- Initialization parameters: Read and merge parameters from configuration files and Shell statements to get the final parameters
- Start compiling: Initialize the Compiler object with the parameters obtained in the previous step, load all configured plug-ins, and execute the object’s run method to start compiling.
- Identify entry: Find all files according to entry
- Compiling module: Starting from the entry file, call all configured Loader to compile the module, find the module dependent on the module, and then recurse this step until all the entry dependent files have gone through this step;
- Complete compilation: After step 4, we get what each module compiled and their direct dependencies;
- Output resources: Assemble chunks containing multiple modules one by one according to the dependency between the entry and modules, and convert each chunk into a separate file to be added to the output. This step is the last chance to modify the output content.
- Output complete: After determining the output content, determine the output path and file name according to the configuration, and write the file content to the system.
Webpack optimization
Narrow the file search
- Optimizing loader Configuration
Loader’s manipulation of file conversion is time-consuming and requires as few files as possible to be processed by Loader.
When using Loader, you can use test, include, and exclude to match the file to which Loader applies rules.
module.exports = {
module: {
rules: [{test: /\.js$/.use: ['babel-loader? cacheDirectory'].include: path.resolve(__dirname, 'src'}]}}Copy the code
- To optimize the
resolve.modules
configuration
Resolve. modules is used to configure which directories Webpack goes to find third-party modules.
The default value of resolve. Modules is [‘node_modules’], which means go to the current directory to find the desired module./node_modules, and so on. /node_modules, no higher level, and so on…
If you know that the installed module is in the./node_modules directory at the root of the project, there is no need to follow the default path:
module.exports = {
resolve: {
modules: [path.resolve(__dirname, 'node_modules')]}}Copy the code
- To optimize the
resolve.alias
configuration
The resolve.alias configuration item maps the original import path to a new one using an alias. Reduces time-consuming recursive parsing operations.
- To optimize the
module.noParse
configuration
The module.noParse configuration allows Webpack to ignore recursive parsing of parts of files that are not modularized, which has the benefit of improving build performance.
const path = require('path');
module.exports = {
module: {
// The entire 'react.min.js' file is not modularized, ignoring the recursive parsing of' react.min.js' file
noParse: [/react\.min\.js$/].}}Copy the code
Divide tasks into multiple subprocesses for concurrent execution
HappyPack splits tasks into multiple child processes and executes them concurrently. The child processes the results and then sends them to the main process. Reduced total build time.
const HappyPack = require('happypack');
const os = require('os');
const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length });
module.exports = {
module: {
rules: [{test: /\.js$/.loader: 'happypack/loader? id=happyBabel'.exclude: /node_modules/}},plugins: [
new HappyPack({
id: 'happyBabel'.loaders: [{
loader: 'babel-loader? cacheDirectory= true',}],// Share the process pool
threadPool: happyThreadPool,
// Allow happypack to output logs
verbose: true,}})]Copy the code
Use auto refresh
Such as:
module.export = {
watch: true.watchOptions: {
// Wait 300ms to execute the action after listening to the change to prevent the file update too fast and recompile too frequently
// the default is 300ms
aggregateTimeout: 300.// Determine whether the file has changed by constantly asking the system whether the specified file has changed
// Query every 1000 milliseconds by default
poll: 1000}}Copy the code
The path for saving files and the time for last editing require memory, and the periodic check period requires CPU and FILE I/O. Therefore, you are advised to reduce the number of files that need to be listened to and reduce the check frequency.
Hot replacement
Hot replacement is when a source code changes, only the changed module is recompiled, and the new output module is replaced with the corresponding old module in the browser.
Enable hot replacement:
webpack-dev-server --hot
Copy the code
To distinguish the environment
Distinguish between development and production environments for different builds
The CDN to accelerate
CDN is also called content distribution network. By deploying resources around the world, users can access resources from the nearest server according to the principle of proximity, thus accelerating the acquisition speed of resources.
CDN actually improves network speed by optimizing problems such as limited network speed and packet loss in the transmission process of physical link layer.
Combined with publicPath to handle:
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const { WebPlugin } = require('web-webpack-plugin');
module.exports = {
output: {
filename: '[name]_[chunkhash:8].js'.path: path.resolve(__dirname, './dist'),
publicPath: '//js.cdn.com/id/'
},
module: {
rules: [{test: /\.css$/.use: ExtractTextPlugin.extract({
use: ['css-loader? minimize'].publicPath: '//img.cdn.com/id/'}})}],plugins: [
new WebPlugin({
template: './template.html'.filename: 'index.html'.// Specify the URL of the CDN directory where the CSS files are stored
stylePublicPath: '//css.cdn.com/id/',}).new ExtractTextPlugin({
// Add a Hash value to the output CSS file name
filename: `[name]_[contenthash:8].css`,]}})Copy the code
The tree shaking optimization
Remove excess code.
webpack --display-used-exports --optimize-minimize
Copy the code
Extract common code
Extraction of common code.
const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
new CommonsChunkPlugin({
// From which chunks
chunks: ['a'.'b'].// The extracted common part forms a new Chunk with the name of the new Chunk
name: 'common'
})
Copy the code
According to the need to load
For the website that uses single-page application as front-end architecture, it will face the problem that a webpage needs to load a large amount of code, because many functions are done in an HTML, which will lead to slow webpage loading, interaction lag, and user experience will be very bad.
The root cause of this problem is to load the code for all functions at once, but the user may only use some of the functions at each stage. So the solution to the above problem is to load only the code corresponding to the function that the user currently needs, which is called load on demand.
Webpack has a powerful built-in feature for splitting code to load on demand. Such as:
- Web pages only load when they first load
main.js
The file, the page will display a buttonmain.js
The file contains only the code to listen for button events and load on demand. - The partitioned one is loaded when the button is clicked
show.js
The file is loaded successfully and then executedshow.js
The function in.
The main. In js:
window.document.getElementById('btn').addEventListener('click'.function () {
// Load the show.js file after the button is clicked, and execute the function exported from the file after the file is loaded successfully
import(/* webpackChunkName: "show" */ './show').then((show) = > {
show('Webpack'); })});Copy the code
The show. In js:
module.exports = function (content) {
window.alert('Hello ' + content);
};
Copy the code
The most critical line in the code is import(/* webpackChunkName: “show” */ ‘./show’). Webpack has built-in support for import(*) statements.
- In order to
./show.js
Create a new one for the entryChunk
; - When the code executes to
import
Is loaded when the statementChunk
Corresponding to the generated file. import
Returns aPromise
, when the file is successfully loadedPromise
thethen
Methodshow.js
Exported content.
In the work of the specific use of the time to change the configuration items as needed ~
reference
- www.webpackjs.com/
- www.kancloud.cn/
First post on Github – talk about Webpack. More content, please poke my blog to understand, can leave a star better 💨