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:

  1. Conditional match: Yestest,include,excludeThree configuration items are matchedLoaderThe file to apply the rules to.
  2. Application rule: Pass the selected fileuseConfigure items to applyLoader, you can only apply oneLoaderOr you can apply a set from back to frontLoaderAnd you can also giveLoaderPass in parameters.
  3. Reset order: one setLoaderThe execution sequence is from right to left by defaultenforceThe option is to make one of themLoaderThe 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:

  1. Initialization parameters: Read and merge parameters from configuration files and Shell statements to get the final parameters
  2. 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.
  3. Identify entry: Find all files according to entry
  4. 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;
  5. Complete compilation: After step 4, we get what each module compiled and their direct dependencies;
  6. 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.
  7. 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 theresolve.modulesconfiguration

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 theresolve.aliasconfiguration

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 themodule.noParseconfiguration

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 loadmain.jsThe file, the page will display a buttonmain.jsThe file contains only the code to listen for button events and load on demand.
  • The partitioned one is loaded when the button is clickedshow.jsThe file is loaded successfully and then executedshow.jsThe 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.jsCreate a new one for the entryChunk;
  • When the code executes toimportIs loaded when the statementChunkCorresponding to the generated file.
  • importReturns aPromise, when the file is successfully loadedPromisethethenMethodshow.jsExported 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 💨