To show sincerity, attach a complete configuration solution:

Overall configuration structure

const path = require('path');

module.exports = {
  // Entry represents the entry, and Webpack performs the first step of the build from entry, which can be abstracted as input.
  / / type can be a string | object | array
  entry: './app/entry'.// There is only one entry and only one file
  entry: ['./app/entry1'.'./app/entry2'].// There is only one entry, and the entry has two files
  entry: { // There are two entrances
    a: './app/entry-a'.b: ['./app/entry-b1'.'./app/entry-b2']},// How to output the result: How to output the final desired code after Webpack has gone through a series of processes.
  output: {
    // The output file is stored in an absolute directory of type string.
    path: path.resolve(__dirname, 'dist'),

    // The output file name
    filename: 'bundle.js'.// Full name
    filename: '[name].js'.// When multiple entries are configured, use the name template to generate different file names for different entries
    filename: '[chunkhash].js'.// Generate a file name based on the hash value of the file content for the browser to cache the file for a long time

    // The string URL prefix for all resources posted online
    publicPath: '/assets/'.// Put it in the specified directory
    publicPath: ' '.// Put it in the root directory
    publicPath: 'https://cdn.example.com/'.// Add it to CDN

    // The name of the export library, type string
    // Without it, the default output format is an anonymous execute now function
    library: 'MyLibrary'.// The type of the export library, enumeration type, var by default
    / / can be umd | umd2 | commonjs2 | commonjs | | amd this | var | assign window | | global | json,
    libraryTarget: 'umd'.// Include useful file path information in the generated code, Boolean type
    pathinfo: true.// Add the file name of Chunk
    chunkFilename: '[id].js'.chunkFilename: '[chunkhash].js'.// The name of the callback function used when JSONP asynchronously loads resources
    jsonpFunction: 'myWebpackJsonp'.// Name of the generated Source Map file
    sourceMapFilename: '[file].map'.// The name of the source module displayed in the browser developer tools
    devtoolModuleFilenameTemplate: 'webpack:///[resource-path]'.// How to asynchronously load resources across domains
    crossOriginLoading: 'use-credentials'.crossOriginLoading: 'anonymous'.crossOriginLoading: false,},// The configuration module is related
  module: {
    rules: [ / / configuration Loader
      {  
        test: /\.jsx? $/.// The re matches the file to use Loader
        include: [ // Only files in this file will be hit
          path.resolve(__dirname, 'app')].exclude: [ // Ignore the file
          path.resolve(__dirname, 'app/demo-files')].use: [ // Use those loaders, in order, from the back to the front
          'style-loader'.// Use the Loader name directly
          {
            loader: 'css-loader'.options: { // Pass some parameters to the html-loader}}]},],noParse: [ // A module that does not need parsing and processing
      /special-library\.js$/  // Match with regex],},// Configure the plug-in
  plugins: [
  ],

  // Configure the rule to find modules
  resolve: { 
    modules: [ // Find the root directory of the module. The default directory is node_modules
      'node_modules',
      path.resolve(__dirname, 'app')].extensions: ['.js'.'.json'.'.jsx'.'.css'].// The extension name of the module
    alias: { // Module alias configuration, used to map modules
       // Map 'module' to 'new-module'. Likewise 'module/path/file' will be mapped to 'new-module/path/file'.
      'module': 'new-module'.// map 'only-module' to 'new-module' with $ending
      // But unlike above, 'module/path/file' is not mapped to 'new-module/path/file'
      'only-module$': 'new-module',},alias: [ // Alias also supports the use of arrays for more detailed configuration
      {
        name: 'module'.// Old module
        alias: 'new-module'.// New module
        // Whether only modules are mapped, if true only 'module' is mapped, if false 'module/inner/path' is mapped
        onlyModule: true,}],symlinks: true.// Whether to follow the file soft link to find the module path
    descriptionFiles: ['package.json'].// Module description file
    mainFields: ['main'].// The name of the field in the description entry file of the module
    enforceExtension: false.// Whether to force import statements to include file suffixes
  },

  // Output file performance check configuration
  performance: { 
    hints: 'warning'.// Output a warning if there is a performance problem
    hints: 'error'.// Output error with performance problem
    hints: false.// Turn off the performance check
    maxAssetSize: 200000.// Maximum file size (bytes)
    maxEntrypointSize: 400000.// Maximum entry file size (bytes)
    assetFilter: function(assetFilename) { // Filter the files to check
      return assetFilename.endsWith('.css') || assetFilename.endsWith('.js'); }},devtool: 'source-map'.// Configure the source-map type

  context: __dirname, // The root directory used by Webpack. The string type must be an absolute path

  // Configure the environment to run the output code
  target: 'web'.// Browser, default
  target: 'webworker'.// WebWorker
  target: 'node'.// node. js, use the 'require' statement to load Chunk code
  target: 'async-node'.// node. js, load Chunk code asynchronously
  target: 'node-webkit'.// nw.js
  target: 'electron-main'.// electron, the main thread
  target: 'electron-renderer'.// electron, render thread

  externals: { // Use global variables provided by the JavaScript runtime environment
    jquery: 'jQuery'
  },

  stats: { // Console outputs log control
    assets: true.colors: true.errors: true.errorDetails: true.hash: true,},devServer: { // DevServer-related configuration
    proxy: { // Proxy to the back-end service interface
      '/api': 'http://localhost:3000'
    },
    contentBase: path.join(__dirname, 'public'), // Configure the DevServer HTTP server file root directory
    compress: true.// Whether to enable gzip compression
    historyApiFallback: true.// Whether to develop HTML5 History API web page
    hot: true.// Whether to enable the module hot replacement function
    https: false.// Whether to enable the HTTPS mode
    },

    profile: true.// Do you want to capture performance information on Webpack builds to analyze what is causing the poor build performance

    cache: false.// Whether to enable caching to improve build speed

    watch: true.// Whether to start
    watchOptions: { // Listen mode options
    // A file or folder that is not listened on and supports regular matching. The default is empty
    ignored: /node_modules/.// 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.// Check whether the specified file has changed. By default, the file is queried every 1000 milliseconds
    poll: 1000}},Copy the code

Webpack

All files in Webpack are modules, converted files by Loader, injected hooks by Plugin, and finally output files composed of multiple modules. Webpack focuses on building modular projects. The advantage of this is that the dependencies between modules can be clearly described to facilitate Webpack to combine and package modules. After Webpack processing, the final output will be static resources that the browser can use.

Advantages of Webpack:

  1. Focus on dealing with modular projects, can do out of the box in one step
  2. Plugin extension, complete and easy to use and flexible
  3. Large and active community

Loader

const path = require('path');

module.exports = {
  // JavaScript executes the entry file
  entry: './main.js'.output: {
    // Merge all dependent modules into a bundle.js file
    filename: 'bundle.js'.// Put the output files in the dist directory
    path: path.resolve(__dirname, './dist'),},module: {
    rules: [{// Use the re to match the CSS file to be converted with the loader
        test: /\.css$/.use: ['style-loader'.'css-loader? minimize'],}]}};Copy the code

Loader can be thought of as a translator with file conversion capabilities. The Mode. rules array in the configuration configates a set of rules that tell Webpack which files to use to load and transform when it encounters them. Note:

  1. The value of the use attribute must be an array of Loader names. Loaders are executed in sequential order.
  2. Each Loader can be passed as a queryString URL, such as CSS-loader? Minimize tells CSS-Loader to turn on CSS compression

In addition to queryString, you can also pass attributes to the Loader by configuring options

use: [
  'style-loader',
  {
    loader: 'css-lader'.options: {
      minimize: true}}]Copy the code

In addition to configuring the Loader in the webpack.config.js file, you can also specify in the source code what Loader to use to process the file, for example

require('style-loader! css-loader? minimize! ./main.css')
Copy the code

Plugin

Plugin is designed to extend Webpack functionality by injecting hook implementations into the build process, which gives Webpack a great deal of flexibility.

const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
  // JavaScript executes the entry file
  entry: './main.js'.output: {
    // Merge all dependent modules into a bundle.js file
    filename: 'bundle.js'.// Put the output files in the dist directory
    path: path.resolve(__dirname, './dist'),},module: {
    rules: [{// Use the re to match the CSS file to be converted with the loader
        test: /\.css$/.use: ExtractTextPlugin.extract({
          // Loader used to convert. CSS files
          use: ['css-loader'],}),}]},plugins: [
    new ExtractTextPlugin({     // Extract the CSS injected into the bundle.js file into a separate file
      // The name of the.css file extracted from the.js file
      filename: `[name]_[contenthash:8].css`,})]};Copy the code

Webpack uses the plugins attribute to configure the list of plugins that need to be used. Plugins are an array in which each item is an instance of a plug-in. When instantiating a component, you can pass in configuration properties supported by that component through the constructor.

DevServer

Actual development may require:

  1. Provide HTTP services instead of using local file previews
  2. Monitor file changes and automatically refresh the web page to achieve real-time preview
  3. Source Map is supported for easy debugging

DevServer starts an HTTP server to service web requests, helps start Webpack, receives file changes from Webpack, and automatically refreshes web pages through WebSocket protocol for real-time preview.

The Webpack-dev-server module needs to be installed

If you try to modify the index. HTML file and save it, you will notice that this does not trigger the above mechanism. The reason for this problem is that Webpack starts up by recursively parsing the file that entry depends on using the entry in the configuration. Only entry itself and dependent files are added to the listener list by Webpack. The index. HTML file is removed from the JavaScript modularization system, so Webpack is unaware of its existence.

Module hot update

Module hot update enables real-time preview by replacing the updated module with the old one and performing it again without reloading the entire web page. To enable module hot update, simply start DevServer with the –hot parameter.

Support the Source Map

Debugging tools can Map code through Source Map to achieve breakpoint debugging on Source code. Start WebPack with the –devtool source-map parameter.

The core concept

  1. Entry: the entrance
  2. Module: A Module corresponds to a file, and Webpack recursively finds all dependent modules starting from the configured Entry
  3. Chunk: a Chunk is a code block. A Chunk is composed of multiple modules for code merging and splitting
  4. Loader: module converter
  5. Plugin: Extension plug-in
  6. Output: Output results

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 searches for the corresponding conversion rule according to the configured Loader, converts the Module, and resolves the Module that the current Module depends on. These modules are grouped in the unit of Entry. An Entry and all its dependent modules are grouped into a group, namely 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.

configuration

How to configure Webpack:

  1. Options that can only be passed in as command-line arguments are the rarest
  2. Options that can only be configured through the configuration file
  3. Options that can be configured either way.

Entry

Entry is a mandatory entry for the configuration module. It can be a string, array, or object.

Context is the current directory where Webpack was started. If you want to change the default configuration, you can:

module.exports = {
  context: path.resolve(__dirname, 'app')   Context must be an absolute path string
}
Copy the code

Chunk

Webpack takes a name for each Chunk that is generated

  1. If the entry is a string or array, only one Chunk is generated, and the name of the Chunk is main
  2. If entry is an object, multiple chunks may be generated, with the name being the name of the key in the object key-value pair.

Configuring Dynamic Entry

If there are multiple pages in the project that need to be configured with an Entry for each page Entry, but the number of these pages may continue to grow, then the Entry configuration will be affected by other factors and cannot be written as a static value. The solution is to set Entry as a function to dynamically return the above configuration:

// synchronization function
entry: (a)= > {
  return {
    a:'./pages/a'.b:'./pages/b',}};// Asynchronous functions
entry: (a)= > {
  return new Promise((resolve) = >{
    resolve({
       a:'./pages/a'.b:'./pages/b'}); }); };Copy the code

Output

Output configures how to output the final desired code, which is an object.

Output configuration item:

filename

Configure the name of the output file. If multiple chunks need to be exported, use templates and variables:

filename: '[name].js'
Copy the code

The built-in variables include id, hash, and chunkhash in addition to name

path

The configuration output file is stored in the local directory. It must be an absolute path of type string

path: path.resolve(__dirname, 'dist_[hash]')
Copy the code

publicPath

In complex projects, there may be resources to build that need to be loaded asynchronously, and they need urls to load.

For example, the constructed resource file needs to be uploaded to the CDN service to accelerate the page opening speed:

filename: '[name]_[chunkhash: 8].js'
publicPath: 'https://cdn.xxx/xxx/'
Copy the code

When HTML is posted online and js files are imported:

<script src='https://cdn.example.com/assets/a_12345678.js'></script>
Copy the code

crossOriginLoading

Some blocks of Webpack output may require asynchronous shelves, and asynchronous loading is implemented via JSONP, which dynamically inserts a tag into the HTML to load asynchronous resources.

The Crossorigin attribute of the script tag can take the following values:

  1. Anonymous does not load this script resource with the user’s cookies
  2. The use-credentials load this script resource with the user’s cookies

It is common to set crossorigin to get detailed error information about the execution of asynchronously loaded scripts.

LibraryTarget and library

They are needed when using Webpack to build a library that can be imported and used by other modules.

  1. Output.librarytarget configures how to export the library
  2. Output. library Specifies the name of the configuration export library

Module

Configure the Loader

Rules Configures the read and parse rules for the module

  1. Conditional match: test, include, exclude
  2. Application rule: The file in the object passesuseConfigure items to apply Loader
  3. Resetting order: Use Enforce to place the execution order of one Loader first or last.
module: {
  rules: [{// Hit JavaScript files
      test: /\.js$/.// Use babel-loader to convert JavaScript files
      / /? CacheDirectory represents a parameter passed to babel-loader to cache Babel compilation results to speed recompilation
      use: ['babel-loader? cacheDirectory'].// Only hit js files in SRC directory to speed up Webpack search
      include: path.resolve(__dirname, 'src')}, {// Hit the SCSS file
      test: /\.scss$/.// Use a set of loaders to process SCSS files.
      // The processing sequence is from back to front, that is, the sass-loader submits the result to CSS-loader, and then to style-loader.
      use: ['style-loader'.'css-loader'.'sass-loader'].// Exclude files in node_modules
      exclude: path.resolve(__dirname, 'node_modules'),}, {// Use file-loader to load non-text files
      test: /\.(gif|png|jpe? g|eot|woff|ttf|svg|pdf)$/.use: ['file-loader'],},]}Copy the code

When the Loader needs to pass in many parameters, it can be described by an Object:

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

Test, include, and exclude also support arrays:

{
  test: [/\.jsx? $/, /\.tsx? $/,include:[
    path.resolve(__dirname, 'src'),
    path.resolve(__dirname, 'tests')],exclude:[
    path.resolve(__dirname, 'node_modules'),
    path.resolve(__dirname, 'bower_modules'),]Copy the code

noParse

You can improve build performance by allowing Webpack to ignore recursive parsing and processing of some unmodularized files.

// Use regular expressions
noParse: /jquery|chartjs/

// Use functions, supported from Webpack 3.0.0 onwards
noParse: (content) = > {
  // Content represents the file path of a module
  // Return true or false
  return /jquery|chartjs/.test(content);
}
Copy the code

Note that omitted files should not contain modular statements such as import, require, define, etc. This will result in code that contains modular statements that cannot be executed in the browser environment.

parser

The difference with noParse configuration items is that Parser is syntactic, whereas noParse only controls which files are not parsed.

module: {
  rules: [{test: /\.js$/.use: ['babel-loader'].parse: {
        amd: false./ / disable AMD
        commonjs: false./ / disable CommonJS
        system: false./ / disable SystemJS
        harmony: false.// Disable ES6 import/export
        requireInclude: false./ / disable the require. Include
        requireEnsure: false./ / disable the require. Ensure
        requireContext: false./ / disable the require. The context
        browserify: false./ / disable browserify
        requireJs: false./ / disable requirejs}}}]Copy the code

Resolve

Resolve configures how Webpack finds files for modules. Webpack built-in JS modular grammar parsing function, the default will use the modular standard agreed rules to find.

alias

Map the original import path to a new import path through an alias.

resolve:{
  alias: {
    components: './src/components/'}}Copy the code

When you import Button from ‘components/ Button ‘, the alias is essentially replaced by import Button from ‘./ SRC /components/ Button ‘.

Alias also supports the $symbol to narrow it down to hitting only import statements ending in a keyword

resolve:{
  alias: {'react$': '/path/to/react.min.js'}}Copy the code

mainFields

Some third-party modules provide several pieces of code for different environments, and this configuration item determines which code Webpack uses first.

extensions

When an import statement does not have a file suffix, Webpack automatically adds the suffix to try to access the file. The default is:

extensions: ['.js'.'.json']
Copy the code

modules

Configure Webpack to find third-party modules in the node_modules directory by default

/ SRC /components:

modules: ['./src/components'.'node_modules']
Copy the code

This allows you to import simply by importing ‘button’

Configure the Plugin

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

The difficulty of using the Plugin is to understand the configuration items provided by the Plugin itself

devServer

hot

Enable the module hot update function of DevServer.

inline

Configure whether to automatically inject the proxy client into the Chunk that will run on the page. The default is automatic injection. If inline is turned on, DevServer will use the proxy client to control the page refresh when the changed code is built. If inline is turned off, DevServer will not be able to directly control the field to be developed, so it will run the page as iframe.

contentBase

Configure the DevServer HTTP server file root, which by default is the current execution directory, usually the project root directory. If you want to set the public directory in the project root directory to the DevServer root directory:

DevServer: {contentBase: paht.join(__dirname,'public')}Copy the code

The files exposed by the DevServer through the HTTP service fall into two categories:

  1. Exposing local files
  2. Expose the results of Webpack builds, because the build results are handed over to DevServer, so you can’t find the build files locally when using DevServer.

ContentBase can only be used to configure rules for exposing local files, and can be turned off by contentBase: false.

headers

This configuration item can inject HTTP response headers into HTTP responses:

devServer: {
  headers: {
    'X-foo':'bar'}}Copy the code

host

Used to configure the address DevServer service listens on

allowedHosts

Configure a whitelist that returns only HTTP hosts in the whitelist

allowedHosts: [
  // Matches a single domain name
  'host.com'.'sub.host.com'.// Host2.com and all subdomains *. Host2.com will match
  '.host2.com'
]
Copy the code

https

By default, the HTTP protocol is used. It can also be used over HTTPS. Switching the HTTPS protocol is also easy:

devServer: {
  https: true
}
Copy the code

DevServer will automatically generate an HTTPS certificate for you, or you can configure it yourself:

devServer:{
  https: {
    key: fs.readFileSync('path/to/server.key'),
    cert: fs.readFileSync('path/to/server.crt'),
    ca: fs.readFileSync('path/to/ca.pem')}}Copy the code

compress

This configuration determines whether gzip compression is enabled. The default is false

Other Configuration Items

Target

The Target configuration allows WebPack to build code for different runtime environments. The target can be one of the following:

Web: for browsers, default option, all code in a file node: for Node.js, use the require statement to load chunk code async-node: for Node.js, load chunk code asynchronously webworker: For the WebWorker electronic-main: for the electron main thread elertron-renderer: for the electron render thread

Devtool

Configures how Webpack generates Source maps. The default value is false. To generate Source maps for built code, you can:

module.export = {
  devtool: 'source-map'
}
Copy the code

Watch and WatchOptions

It supports listening for file updates and recompiling when a file changes, and is disabled by default:

module.export = {
  watch: true
}
Copy the code

When DevServer is used, the listening mode is turned on by default

The watchOptions configuration allows you to control the listening mode more flexibly:

module.export = {
  // watchOptions only make sense if listening mode is enabled
  // Default is false, that is, not enabled
  watch: true.// Listen for the mode runtime parameters
  // Only when listening mode is enabled
  watchOptions: {
    // A file or folder that is not listened on and supports regular matching
    // Empty by default
    ignored: /node_modules/.// 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

Externals

Configure what modules are used in the code Webpack builds that don’t need to be packaged, that is, these templates are provided by the external environment and Webpack can ignore them when packaging.

Externals can be used to tell Webpack that the JavaScript runtime environment already has global variables built into it. For these global variables, you don’t need to package them into the code, but use them directly:

module.export = {
  externals: {
    // Replace jquery in the import statement with the global jquery variable in the runtime
    jquery: 'jQuery'}}Copy the code

ResolveLoader

Used to tell Webpack how to find the Loader

module.exports = {
  resolveLoader: {// Go to the directory to find Loader
    modules: ['node_modules'].// The suffix of the entry file
    extensions: ['.js'.'.json'].// A field specifying the location of the entry file
    mainFields: ['loader'.'main']}}Copy the code

This configuration item is usually used to load the local Loader

Multiple configuration types

There are more flexible ways to describe the configuration required for Webpack by exporting an Object.

Exporting a Function

Most of the time you will need to build multiple copies of the same source code, one for development and one for distribution.

If you export an Object to describe the configuration required for Webpack, you need to write two files. Specify which configuration file to use at startup via webpack –config webpack.config.js.

By exporting a Function, the configuration can be flexibly controlled by JavaScript, and the above requirements can be accomplished with only one configuration file.

const path = require('path');
const UglifyJsPlugin = require('webpack/lib/optimize/UglifyJsPlugin');

module.exports = function (env = {}, argv) {
  const plugins = [];

  const isProduction = env['production'];

  // Compress in build environment
  if (isProduction) {
    plugins.push(
      // Compress the output JS code
      new UglifyJsPlugin()
    )
  }

  return {
    plugins: plugins,
    // The Source Map is not printed in the build environment
    devtool: isProduction ? undefined : 'source-map'}; }Copy the code

When you run Webpack, you pass two arguments to this function:

Env: The webpack-specific environment variable of the current runtime, env is an Object. Read directly to the properties of Object, which need to be set with parameters when starting Webpack. For example, if the startup command is webpack –env.production –env.bao=foo, the env value is {“production”:”true”,”bao”:”foo”}. Argv: represents all command-line arguments passed in when Webpack is started, such as –config, –env, –devtool. You can list all command-line arguments supported by Webpack through Webpack -h. For the configuration files above, execute webpack at development time to build code that is easy to debug, and execute webpack –env.production to build compressed code when you need to build code that is published online.

Export a function that returns a Promise

module.exports = function(env = {}, argv) {
  return new Promise((resolve, reject) = > {
    setTimeout((a)= > {
      resolve({
        // ...})},5000)})}Copy the code

Export multiple configurations

Wepack supports exporting an array, an array summary can contain each configuration, and each configuration is built once.

module.exports = [
  // Use a configuration described by Object
  {
    // ...
  },
  // Take a configuration described by the function
  function() {
    return {
      // ...}},// a configuration that takes the asynchronous function description
  function() {
    return Promise();
  }
]
Copy the code

This is particularly useful for building a library with Webpack that will be uploaded to the Npm repository, since the library may need to contain code in multiple modular formats, such as CommonJS, UMD

conclusion

From the previous configuration, it seems that there are many options, and it is common to use the following experience to determine how to configure Webpack:

  1. To add source files to the build process, Webpack controls entry
  2. To customize the location and name of the output file, configure output
  3. To customize the policy for finding dependent modules, configure Resolve
  4. To customize policies for parsing and converting files, configure module, usually configure Loader in module.rules
  5. Most of the other requirements may be implemented by plugins, configuring plugins