This is the sixth day of my participation in the August More text Challenge. For details, see:August is more challenging

Directory:

1. Webpack concept

2, entrance

  • Default values, objects, strings, arrays, common scenarios (examples)

3, output,

  • Basic usage, advanced advanced (example demonstration)

4, patterns,

  • Pattern Concept, Configuration Mode (example demonstration)

5, loader

  • Loader Concept, three configuration methods, Loader features, and Loader resolution (Example demonstration)

6, the plugin

  • Concept, analysis, usage, (example demonstration)

webpack

Essentially, WebPack is a static Module Bundler for modern JavaScript applications. When WebPack works with an application, it recursively builds a dependency graph that contains every module the application needs, and then packages all of those modules into one or more bundles.

What are the concepts of WebPack

There are four core concepts that need to be understood before configuring to use WebPack

  • The entrance (entry)
  • Output (output)
  • loader
  • The plug-in (plugins)

What follows is a high-level overview of these concepts, along with detailed related use cases for specific concepts

The entrance

The entry point indicates which module WebPack should use to start building its internal dependency graph. After entering the entry point, WebPack will find out which modules and libraries the entry point (directly and indirectly) depends on.

Each dependency is then processed and finally exported to files called bundles, a process we will discuss in detail in the next section.

You can specify an entry starting point (or entry starting points) by configuring the Entry property in the WebPack configuration. The default value is./ SRC.

Let’s look at the simplest example of entry configuration:

The Entry property can be configured in a number of ways, depending on the specific needs of the application. More information can be found in the Entry Starting point section.

exit

The output property tells WebPack where to output the bundles it creates and how to name them. The default value is./dist.

Basically, the entire structure of the application is compiled to a folder in the output path that you specify.

You can configure these processes by specifying an output field in the configuration:

In the example above, we use the output.filename and output.path attributes to tell the Webpack bundle name and where we want the bundle generation (emit) to go.

In case you want to know what the path module imported at the top of the code is, it is a core Node.js module that operates on file paths.

You may find the term emitted by a emit (emitted by a emit) throughout our document and plugin API. It is a specific term for “produced” or “released.”

Output properties have many more configurable properties. If you want to learn more about the concept of output properties, you can read the concepts section to learn more.

loader

Loader allows WebPack to process files that are not JavaScript (WebPack itself only understands JavaScript). Loader converts all types of files into valid modules that WebPack can handle, and then you can take advantage of WebPack’s packaging capabilities to process them.

Essentially, the WebPack Loader converts all types of files into modules that the application’s dependency graph (and eventual bundle) can refer to directly.

Note that the Loader can import any type of module (such as.css files), which is a webPack-specific feature that may not be supported by other packagers or task executors. We believe this language extension is necessary because it allows developers to create more accurate dependency diagrams.

At a higher level, the Loader has two goals in the Configuration of WebPack:

1. The test attribute identifies the file or files that should be converted by the corresponding Loader.

2. The use attribute, which loader should be used for the conversion.

In the previous configuration, we defined the rules property for a single Module object, which contains two required properties: test and use. This tells the WebPack compiler the following:

“Hey webpack compiler, when you come across ‘paths that are parsed to ‘.txt’ in require()/import statements’, use raw-Loader to convert it before you package it.”

It is important to remember that when loader is defined in the WebPack configuration, it is defined in module.rules, not rules. However, WebPack gives serious warnings when defining errors. In order for you to benefit from this, WebPack will “give a serious warning” if you don’t do it the right way

model

By selecting either Development or Production and setting the mode parameter, you can enable webPack’s built-in optimizations for that mode

The plug-in

Loaders are used to convert certain types of modules, while plug-ins can be used to perform a wider range of tasks. Plug-ins can range from packaging optimizations and compression to redefining variables in the environment. The plug-in interface is extremely powerful and can be used to handle a wide variety of tasks.

To use a plug-in, all you need to do is require() it and then add it to the plugins array. Most plug-ins can be customized by option. You can also use the same plug-in multiple times in a configuration file for different purposes, and you need to create an instance of it by using the new operator.

Webpack offers many plugins available out of the box! Check out our list of plug-ins for more information.

Using plug-ins in a WebPack configuration is straightforward, but there are many use cases worth exploring further.

Entry (beginning of dependency graph)

As we mentioned in the inception, there are several ways to define entry properties in a WebPack configuration. In addition to explaining why it might be useful, we’ll show you how to configure the entry property.

Entry takes three forms of value: object, string, and array

The default value

The Entry option is not configured in WebPack

module.exports = {
	output: {
		filename: 'entry.js',
		
		path: path.resolve(__dirname, 'dist')
	},
	module: {
		rules: [{
			test: /\.css$/,
			use: [
				'style-loader',
				'css-loader'
			]
		}]
	},
	plugins: [
		new CleanWebpackPlugin(['dist']),
		new HtmlWebpackPlugin({
			title: 'Output Management'
		})
	]
};
Copy the code

The above configuration package directory looks like this (dist is the package directory, SRC is the pre-package resource directory)

The default is to find index.js in the SRC directory to package

Entry Indicates the object form of an entry

Object syntax can be cumbersome. But it is also the most extensible way to define an entry in an application.

“Extensible Webpack configurations” means that they are reusable and can be used in combination with other configurations. This is a popular technique for separating concern from the environment, build target, and runtime. They are then combined using specialized tools such as Webpack-merge.

key

The object form for the key can be a simple string, such as ‘app’, ‘vebdors’, ‘entry-1’, etc.

entry: {
	'entryTest': './src/entry-1.js'
},
output: {
	filename: '[name].js',
	path: path.resolve(__dirname, 'dist')
},
Copy the code

The above configuration is generated after packaging

value

Value can be a string, which can be either a file path or an NPM module

entry: {
	'my-lodash': 'lodash'
},
output: {
	filename: '[name].js',
	path: path.resolve(__dirname, 'dist')
},
Copy the code

The above configuration is generated when packaged

Value can also be an array, and the elements in the array need to be reasonable string values.

entry: {
    main: ['./src/index.js', 'lodash']
},
output: {
	filename: '[name].js',
	path: path.resolve(__dirname, 'dist')
}
Copy the code

The above configuration is packaged and generated

Entry string

const config = {
  entry: './path/to/my/entry/file.js'
};

module.exports = config;

Copy the code

The string form is shorthand for the following form

const config = {
  entry: {
    main: './path/to/my/entry/file.js'
  }
};
Copy the code

Array entry

const config = {
	entry: ['./app.js', 'lodash']
};
Copy the code

Equivalent to the following object form

const config = {
	entry: {
		main: ['./app.js', 'lodash']
	}
};
Copy the code
entry: ['./src/print.js', './src/index.js'],
output: {
	filename: '[name].js',
	path: path.resolve(__dirname, 'dist')
},
Copy the code

The above configuration is generated after packaging

“What happens when you pass an array to entry? Passing an Array of File Paths to the entry property creates a multi-main Entry. Passing in an array is useful when you want multiple dependency files to be injected together and graph their dependencies into a chunk.

Common scenarios

1. Separate the entry of apps and third-party libraries

const config = {
  entry: {
    app: './src/app.js',
    vendors: './src/vendors.js'
  }
};
Copy the code

What’s this? On the face of it, this tells us that WebPack creates the dependency graph starting with app.js and vision.js. These dependency diagrams are completely separate and independent of each other (each bundle has a WebPack bootstrap). This is more common in single page applications that have only one entry point (excluding vendors).

Why is that? This setting allows you to use the CommonsChunkPlugin to extract the Vendor Reference from the application bundle into the Vendor bundle, Replace the vendor reference with a call to webpack_require(). If there is no vendor code in the application bundle, you can implement a common pattern called long-acting caching in WebPack.

2. Multipage applications

const config = {
  entry: {
    pageOne: './src/pageOne/index.js',
    pageTwo: './src/pageTwo/index.js',
    pageThree: './src/pageThree/index.js'
  }
};

Copy the code

What’s this? We tell WebPack that we need three separate dependency graphs (as shown in the example above).

Why is that? In a multi-page application, the server will fetch a new HTML document for you. The page reloads the new document, and the resources are redownloaded. However, this gives us a special opportunity to do many things:

  • Use the CommonsChunkPlugin to create bundles for application shared code between each page. Multi-page applications can greatly benefit from these technologies by being able to reuse large amounts of code/modules between entry points as entry points increase.

A rule of thumb: Use only one entry point per HTML document.

Output (output)

Configuring the Output option controls how WebPack writes the compile file to the hard disk. Note that only one output configuration is specified, even though multiple entry points can exist

The minimum requirement for configuring the Output property in WebPack is to set its value to an object, including the following:

  • Filename Indicates the name of the output file.
  • The absolute path of the destination output directory path.

usage

const config = {
  output: {
    filename: 'bundle.js',
    path: '/home/proj/public/assets'
  }
};

module.exports = config;
Copy the code

This configuration outputs a single bundle.js file to the /home/proj/public/assets directory.

Multiple entry points

If the configuration creates multiple separate “chunks” (for example, using multiple entry points or using a plug-in such as CommonsChunkPlugin), then substitutions should be used to ensure that each file has a unique name

{ entry: { app: './src/app.js', search: './src/search.js' }, output: { filename: '[name].js', path: __dirname + '/dist'}} // Write to hard disk:./dist/app.js,./dist/search.jsCopy the code

Senior advanced

Here’s a complex example using CDN and resource hash:

output: {
  path: "/home/proj/cdn/assets/[hash]",
  publicPath: "http://cdn.example.com/assets/[hash]/"
}
Copy the code
entry: {
		index: './src/index.js',
		print: './src/print.js'
},
output: {
	filename: '[name].js',
	path: path.resolve(__dirname, 'dist/[hash]'),
	publicPath: "http://cdn.example.com/assets/[hash]"
}
Copy the code

The preceding configuration output directory is

The file path referenced in HTML changes

If the publicPath of the final output file is not known at compile time, publicPath can be left blank and dynamically set when the entry starting file is run. Can be set at the start of the entry

__webpack_public_path__ = myRuntimePublicPath
Copy the code

Mode (mode)

Provide a mode configuration option to tell WebPack to use the built-in optimizations for the appropriate mode. Its value is a string. ‘None ‘, ‘development’, and ‘production'(default).

development

Process.env.node_env is set to development. Enable NamedChunksPlugin and NamedModulesPlugin.

production

Process.env.node_env is set to production. Enable FlagDependencyUsagePlugin FlagIncludedChunksPlugin, ModuleConcatenationPlugin NoEmitOnErrorsPlugin, OccurrenceOrderPlugin SideEffectsFlagPlugin and UglifyJsPlugin.

none

Opts out of any default optimization options

If not, WebPack sets Production to the default value of mode

### Two configuration forms

1. In the configuration file

module.exports = {
  mode: 'production'
};
Copy the code

2. Pass it from CLI parameters

webpack --mode=production
Copy the code

If you want to change the behavior based on the mode variable in webpack.config.js, you must export functions instead of objects

Remember, only NODE_ENV is set, and mode is not automatically set.

The packaging information is as follows

loader

Loader converts the source code of a module. Loader allows you to preprocess files when importing or “loading” modules. Thus, loaders are similar to “tasks” in other build tools and provide a powerful way to handle front-end build steps.

  • Loader can convert files from different languages (such as TypeScript) to JavaScript.
  • Convert an inline image to a Data URL.
  • Allows you to import CSS files directly from JavaScript modules

You can use loader to tell WebPack to load CSS files, or to convert TypeScript to JavaScript. To do this, first install the corresponding loader

npm install --save-dev css-loader
npm install --save-dev ts-loader
Copy the code

Webpack is then instructed to use csS-Loader for each.css file, and ts-Loader for all.ts files

module.exports = {
  module: {
    rules: [
      { test: /\.css$/, use: 'css-loader' },
      { test: /\.ts$/, use: 'ts-loader' }
    ]
  }
};
Copy the code

Using the loader

  • Configuration (recommended) : Specify the loader in the webpack.config.js file.
  • Inline: Loader is explicitly specified in each import statement.
  • CLI: Specify them in shell commands.

1. Configuration (recommended) : specify the loader in the webpack.config.js file.

Module. rules allows you to specify multiple loaders in your WebPack configuration. This is a concise way to show loader and helps keep the code concise. It also gives you a global overview of each loader:

module: {
rules: [
  {
    test: /\.css$/,
    use: [
      { loader: 'style-loader' },
      {
        loader: 'css-loader',
        options: {
          modules: true
        }
      }
    ]
  }
]
}
Copy the code

After the above configuration, the CSS we introduced in JS is added to the HTML file as shown in the following figure.

2. Inline: Specify loader explicitly in each import statement.

import Styles from 'style-loader! css-loader? modules! ./styles.css';Copy the code

Loader can be specified in an import statement or in any method equivalent to “import”. Use! Separate loaders from resources. Each separate section is resolved relative to the current directory.

Options can pass query parameters, such as? Key =value&foo=bar, or a JSON object, such as? {” key “:” value “, “foo” : “bar”}.

Delete CSS loaders and style-loaders from config.js, and then configure the following in the import CSS file:

import _ from 'lodash'; // import './style.css'; import 'style-loader! css-loader? modules! ./loader-inline.css';Copy the code

Generated effect

Use module.rules whenever possible, as this reduces the amount of code in the source code and allows you to debug and locate problems in the Loader faster if an error occurs.

3. CLI: Specify them in shell commands.

webpack --module-bind jade-loader --module-bind 'css=style-loader! css-loader'Copy the code

This uses jade-loader for.jade files and style-loader and css-loader for.css files.

Loader features

  • Loader supports chained delivery. Be able to pipeline resources. A set of chained loaders will execute in reverse order. The first loader in the loader chain returns the value to the next loader. On the last loader, return the JavaScript that WebPack expects.
  • Loaders can be synchronous or asynchronous.
  • Loader runs in Node.js and can perform any possible operation.
  • Loader receives query parameters. Used to pass the configuration to loader.
  • Loader can also be configured using the Options object.
  • In addition to using the common main property of package.json, you can export the normal NPM module as a Loader by defining a Loader field in package.json.
  • Plugins can bring more features to loaders.
  • Loader can generate additional arbitrary files.

Loader adds more power to the JavaScript ecosystem through preprocessor functions. Users now have more flexibility to introduce fine-grained logic, such as compression, packaging, language translation, and more.

Parsing the loader

Loader follows standard module resolution. In most cases, loader will resolve from the module path (usually considered to be NPM install, node_modules).

The Loader module needs to be exported as a function and written in Node.js compatible JavaScript. NPM is usually used for management, but you can also treat custom loaders as files in your application. By convention, loaders are usually named xxx-Loader (for example, json-loader). For more information, see How to Write a Loader? .

plugin

Plug-ins are the backbone of WebPack. Webpack itself is built on top of the same plugin system that you use in your WebPack configuration!

Plug-ins are designed to solve other things that the Loader cannot do.

Analyze the

The WebPack plug-in is a JavaScript object with the Apply attribute. The Apply attribute is called by the WebPack Compiler, and the Compiler object is accessible throughout the compilation lifecycle.

ConsoleLogOnBuildWebpackPlugin.js

const pluginName = 'ConsoleLogOnBuildWebpackPlugin'; class ConsoleLogOnBuildWebpackPlugin { apply(compiler) { compiler.hooks.run.tap(pluginName, Compilation => {console.log(" Webpack build process started! ") ); }); }}Copy the code

The first argument to the tap method of compiler Hook should be a hump-named plug-in name. It is recommended to use a constant for this so that it can be reused across all hooks.

usage

Since plug-ins can carry parameters/options, you must pass new instances to the plugins property in the WebPack configuration.

webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin'); // install const webpack = require('webpack'); // Access the built-in plugin const path = require('path'); const config = { entry: './path/to/my/entry/file.js', output: { filename: 'my-first-webpack.bundle.js', path: path.resolve(__dirname, 'dist') }, module: { rules: [ { test: /\.(js|jsx)$/, use: 'babel-loader' } ] }, plugins: [ new webpack.optimize.UglifyJsPlugin(), new HtmlWebpackPlugin({template: './src/index.html'}) ] }; module.exports = config;Copy the code

Node API

Even with the Node API, the user should pass in the plugins attribute in the configuration. Compiler. Apply is not recommended.

some-node-script.js

const webpack = require('webpack'); // access webpack runtime (Runtime) const configuration = require('./webpack.config.js'); let compiler = webpack(configuration); compiler.apply(new webpack.ProgressPlugin()); compiler.run(function(err, stats) { // ... });Copy the code

Did you know: The example you saw above is very similar to the WebPack runtime itself? Hidden in the Wepback source code are a number of usage examples that you can use in your own configurations and scripts.