Webpack (including 4) configuration detailed __webpack packaging tools

Source: Internet
Author: User
Tags file copy postcss css preprocessor
Preface

Source

Familiar with Webpack and WEBPACK4 configuration.

The main difference between WEBPACK4 and 3 is the so-called 0 configuration, but we have to configure ourselves to meet our project requirements, but we can use some Webpack preset values. At the same time, Webpack is also split into two parts, Webpack and Webpack-cli, both of which need to be installed locally.

We have an experience by implementing a Vue development template (Vue init webpack template, which is actually not very much related to vue). In the configuration process, you will try to use WEBPACK4 related content.

This article does not make a complete introduction to the Webpack configuration, focusing on the areas needing attention in the configuration process. View code comments better reading, full configuration and detailed comments visible source code. The configuration is located under the Build folder.

the chapters associated with version 4 add symbol ④.

It is important to note that our Webpack code is run in the node environment, which can use the node API, but our business code (SRC) is not able to use the node API. Basic Public Configuration

Due to the context,entry (Chunk inlet) in the Webpack configuration, the configuration of loaders in output and module.rules is generally common in both development mode and production mode, so we extract Webpack.base.js file, for reuse. The output portion of which is as follows:

Output: {
  
  path:path.resolve (__dirname, ' ... /dist/'),//resource file output write path
  filename: ' static/js/[name].[ Chunkhash].js ',///Use Chunkhash to add file name to update and cache processing
  chunkfilename: ' static/js/[name].[ Chunkhash].js '
}

You need to be aware of: file name Hash

The hash is used in the name of the file output, such as [name]. [Hash].js, in general, Webpack provides three kinds of hash: [Hash]: Hash of all the contents of this package. [Chunkhash]: Each chunk is calculated according to its own content. [Contenthash]: Provided by the CSS extraction plug-in, calculated according to its own content.

The use of three kinds of hash, we in the optimization section again, first priority to use [Chunkhash]. Loader Priority

Loader priority needs to be noted for two points, with the test configuration priority: Multiple loader are configured under the same test, and priority loader is placed after the configuration array, as for less processing:

{
  test:/\.less$/, use
  : [
    ' Style-loader ', 
    ' css-loader ', ' 
    postcss-loader 
    ', ' Less-loader '
  ]
}
Different test priority: such as the processing of JS files requires two test configuration, using Eslint-loader and Babel-loader, but can not be configured in a configuration object, you can use the enforce: ' pre ' emphasis on priority, by eslint- Loader priority treatment.
{
  test:/\. (Js|vue) $/,
  loader: ' Eslint-loader ',
  enforce: ' Pre ',
},
{
  test:/\.js$/,
  loader: ' Babel-loader '
}
CSS Preprocessor Configuration

We use the less file's loader configuration [' Vue-style-loader ', ' css-loader ', ' postcss-loader ', ' less-loader '], using the @import URL (demo.less) as an example: l Ess-loader first deal with less syntax postcss-loader prefix addition and other processing css-loader the content into the CSS file where the @import in Vue-style-loader will generate style tags, CSS Content Inserts HTML

Vue-style-loader function is similar to Style-loader

However, because of the single file components in the Vue, there are two different situations:

The style in the. Vue file:
Vue-loader will handle the. Vue single file component, the various lang= "types" within the. Vue Single file component we can configure different vue-loader in the options for loader, as Vue-loader is built with Postcs s handles the CSS, so we don't need to configure postcss-loader here

{
  test:/\.vue$/,
  loader: ' Vue-loader ',
  options: {
    loaders: {
      less: ['//Xxx-loaders '],
      scss: ['//Xxx-loaders '],}}}

JS introduction of the direct introduction of the style file:
such as import ' demo.less ' in Main.js, the style file introduced in this way, in addition to the Vue-loader processing scope, so still need to configure Postcss-loader.

Because of this difference, we will encapsulate the configuration of the CSS preprocessor file as a function, generate the corresponding configuration by the Usepostcss parameter, put the file into the Utils.js file, and place the Vue-loader configuration in the Vue-loader.js file.

That is, the configuration of the CSS preprocessor we need to configure within the Vue-loader and Webpack two times.

Write this article readme.md period Vue-loader released V15 version, need to cooperate with plug-in use, no more two times to configure Postcss-loader

Postcss-loader is a powerful CSS processing tool, we split POSTCSS configuration, new postcss.config.js configuration file

Module.exports = {
  plugins: {
    //process @import
    ' Postcss-import ': {},
    //process CSS URL
    ' postcss-url ': {},< c6/>//automatic prefix
    ' autoprefixer ': {"
      browsers": [
        "> 1%",
        "last 2 Versions"
      ]
    }
  }
}

In addition to the functional plug-ins that are listed in the note, we may also use NEXTCSS (the new CSS syntax) to Px2rem/px-to-viewport mobile End adapter-related plug-ins. Babel-loader

We use Babel to compile the browser can not recognize the JS, class JS syntax, such as Escape es6+, JSX and so on. Also split the Babel-loader configuration, you need to create. BABELRC and configure:

{
  "presets": [[/* * * * *  babel-preset-env
       *  can automatically enable the required Babel plug-in according to the configured target run environment.
       * *
      "env", {
        "modules": false,//Turn off Babel for ES module processing
        "targets": {//target run environment
          "browsers": [> 1% "," Last 2 Versions "," Not IE <= 8 "
        }
      }]
  ,
  " plugins ": [
    " Syntax-dynamic-import "/ /Asynchronous Load Syntax compilation plug-in
  ]
}
Media Resources Loader

We also need to the picture, video, fonts and other files for loader configuration, in font files as an example, the main use is Url-loader:

{
  /**
   * end \? * Matching belt? Resource Path
   * We introduce a third-party CSS font style The version information with the query string may be in the reference path of the font
  /test:/\. ( WOFF2|WOFF|EOT|TTF|OTF) (\?. *)? $/,
  /**
   * Url-loader
   * will cooperate with Webpack to make replication of the resource introduction path, such as the CSS extracted into a separate file, there may be 404 errors can see the extraction of JS CSS part of the solution
   * will be the Web Pack output path is the basic path, the name configuration for specific output
   * Limit unit is byte, less than the size of the file will be compiled into Base64 write JS or HTML
   * *
  loader: ' Url-loader ', C12/>options: {
    limit:10000,
    name: ' static/fonts/[name].[ Hash:7]. [ext] ',
  }
}
static file copy

Direct references (absolute paths) and resource paths determined by code execution should be in static files that are not webpack compiled, so we place them in separate folders (such as static) and copy them to our output directory after the code is packaged, and we use Copy-webpack-plugin automatically completes this work:

Const Copywebpackplugin = require (' copy-webpack-plugin ')

//In development mode, writes the file to memory
new Copywebpackplugin ([
  {
    from:path.resolve (__dirname, ' ...) /static '), to
    : ' Static ',
    ignore: ['. * ']
  }
]

This plugin crashes when too many copies of files are not known to be resolved. Production Mode production

Let's start with the configuration of the production pattern. Add script Scripts command

Add under Package.json

' Scripts ': {
  ' build ': ' Node Build/build.js '
}

Then use the NPM Run Build command to execute the node build/build.js, we do not use the Webpack webpack.prod.config.js command to execute the configuration file, but in the build.js, do some file deletion process, Start Webpack again. Creating Build.js Logic

Mainly two work, the introduction of the Rimraf module to delete the webpack generated before the specified file, start the Webpack, and at different stages to give a different message.

Set the current production environment in the first line
Process.env.NODE_ENV = ' production '

const WEBPACK = require (' webpack ')
const RM = require ( ' Rimraf ')
const WEBPACKCONFIG = require ('./webpack.prod ')
//Delete the contents of the Webpack output directory, or delete only the child files such as static
RM ( WebpackConfig.output.path, err => {
  //Webpack boot in production mode
  Webpack (Webpackconfig, (err, stats) => {
    //Output Some status information
  })
}

See source code comments for more details. Production mode configuration file

New Webpack.prod.js file, using

Const MERGE = require (' webpack-merge ')//private Merge Webpack configuration package
Const WEBPACKBASECONFIG = require ('./webpack.base ')
Module.exports = Merge (Webpackbaseconfig, {
  //Production mode configuration
})

Merge the basic configuration and production mode unique configuration, and then we start the production mode of the Webpack configuration information to fill out. ④mode Presets

This is the new API for Webpack4, with three preset values: Development,production,none, we choose Mode in the production mode: ' Production ', Webpack4 This configuration is enabled by default: Plugin Flagdependencyusageplugin: Should be deleted unwanted code, other plug-ins rely on Flagincludedchunksplugin: should be deleted unwanted code, other plug-ins rely on Moduleconcatenationplugin: Scope elevation Webpack3 Scope hosting Noemitonerrorsplugin: Encountered error code does not jump out of occurrenceorderplugin Sideeffectsflagplugin UGLIFYJSPLUGIN:JS Code Compression Process.env.NODE_ENV value is set to production

So these default enabled content we don't need to reconfigure.

The last point set the Process.env.NODE_ENV value to production is actually using the Defineplugin plugin:

New Webpack. Defineplugin ({
  "Process.env.NODE_ENV": Json.stringify ("Production") 
})

So we can use Process.env.NODE_ENV in business code, such as making judgments, using the development interface or the online interface. If we need to judge the current environment in Webpack, we also need to set Process.env.NODE_ENV = ' production ', which is what we do in the first line of Build.js. add webpack bundles to HTML file we can only configure the JS file as a portal when using Webpack configuration entry, webpack the bundles not automatically associated with our project's HTML file. We need to manually add <script src= "./bundles.js" ></script> (which may also include a later extracted CSS file) to an HTML file. We can do this automatically using the Html-webpack-plugin plug-in. This step is not required when you are only using Webpack to package JS without HTML file requirements.

Const Htmlwebpackplugin = require (' Html-webpack-plugin ')
plugins: [
  new Htmlwebpackplugin ({
    filename: Path.join (__dirname, '.. /dist/index.html '),//File Write path
    template:path.join (__dirname, ' ... /src/index.html '),//template file path
    inject:true//JS etc bundles Insert HTML position head/body etc
  })
]

If Htmlwebpackplugin is not configured, it creates an HTML file in which filename is more important in development mode. ④ extracts the CSS part of JS to a separate file

The classmate who used Webpack3 should be familiar with the Extract-text-webpack-plugin plug-in (the old plug-in), in order to try Webpack4, I do not want to use the @next version of this plug-in, so I chose a new alternative plugin Mini-css-extract-plugin (as a new plug-in).
As with the old plug-in, it also needs to be configured in the loader and plugin parts of the Webpack, but the new plug-in provides a separate loader, and the loader part is configured differently from the old one. The configuration is as follows:

Loader part

' js
const MINICSSEXTRACTPLUGIN = require ("Mini-css-extract-plugin")
//...
[
  {
    loader:MiniCssExtractPlugin.loader,
    options: {
    *
    * * Replication CSS file resource path
    * webpack3.x configured in  Extract-text-webpack-plugin Plugin
    * Because the external chain in the CSS file is relative to the CSS,
    * We pull out of the CSS file in a possible separate CSS folder
    * Reference Other such as Img/a.png will address error
    * In this case, you need to configure it individually. /, replication of the path of the resource/
    Publicpath: '. /' 
  },
  {
    loader: ' Css-loader ',
    options: {}
  },
  {
    loader: ' Less-loader ',
    Options: {}
  }
]
'

Plugin part

' JS
new Minicssextractplugin ({
  //output to a separate CSS folder under
  filename: "static/css/[name].[ Chunkhash].css "
})" '

You can see that this loader is also configured in the CSS preprocessor section, where we have extracted the CSS preprocessor configuration into the Utils.js file function, so here too, we use the extract parameter to decide whether or not to extract.

Recall that the previous use of Style-loader or Vue-style-loader will create a label that inserts the content of the CSS directly into the HTML. After extracting the standalone CSS file, the work of inserting into HTML is done by the Html-webpack-plugin plug-in, and this part of the responsibility is duplicated, so we need to use the extract parameter to do something like the following:

if (options.extract) {return
  [Minicssextractplugin.loader, ... otherloaders]
} else {return
  [' Vue-style-loader ', ... otherloaders]
}
④ split JS code

This is a very important part of the Webpack configuration, affecting our use of browser caching rationality, the impact of the page resource loading speed, the JS to a reasonable split, can effectively reduce each time we update the code to affect the scope of the file.
Students who have used WEBPACK3 must be clear, we will generally extract so many files manifest.js (Webpack runtime, that is, Webpack parsing other bundle code, etc.), vendor.js (the library in Node_modules), App.js (real Project business code). In the Webpack3 we use the Webpack.optimize.CommonsChunkPlugin plug-in to extract, Webpack4 we can use the optimization configuration item directly to configure (of course still can use plug-in configuration):

 The/** * Optimization section includes code splitting
 * and code split extraction for the runtime (manifest) for a separate runtimechunk configuration *
/optimization: {
  splitchunks: {
    Chunks: "All",
    cachegroups: {
      //Extract Node_modules code
      vendors: {
        test:/[\\/]node_modules[\\/]/,
        Name: "Vendors",
        chunks: "All"
      },
      Commons: {
        //Async Settings Extract common code in asynchronous code
        chunks: "Async"
        Name: ' Commons-async ',
        /**
         * minsize defaults to 30000
         * Want to make the code split really according to our settings
         * need to reduce the
         minsize
        / minsize:0,
        //At least two chunks common code
        minchunks:2
      }}
  ,
  /**
   * corresponds to the original minchunks: Infinity
   * Extract webpack run-time code
   * directly to TRUE or set name */
  runtimechunk: {
    name: ' Manifest '
  }< c36/>}

You can also configure a development dependency that will not change into a separate entry, such as:

Entry: {
  app: ' Index.js ',
  vendor2: [' vue ', ' vue-router ', ' Axios ']
}
Development Mode Development

The difference between the development model and the production mode is that the code is frequently run during development, so many things are not recommended for configuration in the development mode, such as CSS file extraction, code compression, etc. So for some write public configuration file, but the development mode does not need the function, we need to do similar modification: Process.env.NODE_ENV = = ' production '? True:false, such as whether to configure extraction loader minicssextractplugin.loader in CSS preprocessing. In addition, some are only configured in production mode, such as Minicssextractplugin and JS code split optimization.

Development mode We need a development service, to help us complete real-time updates, interface agents and other functions. We use Webpack-dev-server. NPM installation is required. Add script Scripts command

Again, add under Package.json

"Scripts": {
  "dev": "Webpack-dev-server--config./build/webpack.dev.js"
}

Use--config to specify the configuration file, because the command calls Webpack-dev-server run directly, so we write the configuration directly, you can not like production mode to write the calling logic. Development Mode configuration file

Create a new Webpack.dev.js file, using the same:

Set the current environment in the first line for the development environment
Process.env.NODE_ENV = ' development '
const MERGE = require (' webpack-merge ')// Private Merge Webpack configuration package
Const WEBPACKBASECONFIG = require ('./webpack.base ')
module.exports = Merge ( Webpackbaseconfig, {
  //Development mode configuration
})
④mode Presets

Similarly, in development mode we can configure mode as development, and also by default some features are enabled: Plugin Namedchunksplugin: Use entry name to do chunk logo Namedmodulesplugin: The value of module identification Process.env.NODE_ENV is set to the development Development Service configuration using the module's relative path non-self increasing ID devserver

Document

Devserver: {
  clientloglevel: ' Warning ',
  inline:true,//
  start hot update
  hot:true,
  //Full Screen output error information
  on the page Overlay: {
    warnings:true,
    errors:true
  },
  //Show Webpack Build Progress
  progress:true,
  //Dev-server Service path
  contentbase:false,
  compress:true,
  host: ' localhost ',
  port: ' 8080 ',
  //Open Browser
  automatically Open:true,//
  can interface agent configuration proxy:xxx,///
  with Friendly-errors-webpack-plugin plug-in with
  Quiet:true,
  Publicpath: '/'
}
Other plugins

Devserver need to use Plug-ins when hot updates are used:

Plugins: [
  new Webpack. Hotmodulereplacementplugin ()
]

To optimize Webpack output information, you need to configure:

Const Friendlyerrorsplugin = require (' Friendly-errors-webpack-plugin ')
plugins: [
  New Friendlyerrorsplugin ( )
]
Attention MattersHot update: In the use of hot update, our chunk name can not use [hash] to do the identification, file name changes can not be hot update, so the original configuration in the public configuration in the output of the file name configuration in the production and development mode configuration, the development mode to remove [hash]
FileName: ' static/[name].js ', 
chunkfilename: ' Static/[id].js '
Htmlwebpackplugin: In production mode, we write HTML files to dist, but in development mode, there is no actual write process, and Devserver service content after the start of the contentbase, the two need to be consistent, so we will The Htmlwebpackplugin configuration is also divided into production and development patterns, which are used in development mode:
New Htmlwebpackplugin ({
  filename: ' index.html ',//File write path, previous path corresponds to contentbase in devserver
  Template: Path.resolve (__dirname, '.. /src/index.html '),//template file path
  inject:true
})
Optimized Configuration ExtractionDevelopment patterns and production patterns are enabled for some features, such as whether CSS is extracted. Path configuration, such as file output path and filename, Publicpath in output (only path is configured in code output, no Publicpath is configured, and the static of this part of the path is written to the output name of each resource). can refer to Webpack in Publicpath detailed), service configuration such as Port.

We can extract it into a standalone config file (not done in this code). Split JS Code

In the production mode of the split JS code section We have talked about how to split, so in order to better analyze our split is reasonable, we can configure a bundle composition analysis of the plug-in.

Const Bundleanalyzer = require (' Webpack-bundle-analyzer ')
plugins: [
  New Bundleanalyzer.bundleanalyzerplugin ()
]
Hash Curing

We use the hash changes in the file name to update the resource files, so reasonable use of the cache, we require a reasonable split file, in the content update, the minimum impact of the hash file name. [Hash],[chunkhash],[contenthash] is used here. However, the default processing of Webpack to hash is not satisfactory, this part of the optimization can refer to the Webpack-based persistent cache scheme multiple pages

The multiple-page configuration code is located in the Muilt-pages branch. We only need to make a few changes to the current entry page and index page for example. Entry Changes

The two-page JS portal is configured in the Webpack entry:

Entry: {
  /**
    * entrance, Chunkname: path
    * Multi-entry can be configured with multiple * *
  main: './src/main.js ',
  entry: './src/entry.js '
}

You can also set up your own project structure and use the node API to dynamically read to get the current multiple-page entry. Htmlwebpackplugin Changes

You need to configure multiple Htmlwebpackplugin according to the number of pages:

New Htmlwebpackplugin ({
  filename:path.join) (__dirname, '. /dist/main.html '),//File Write path
  template:path.join (__dirname, ' ... /src/index.html '),//template file path
  inject:true,//Insert position
  chunks: [' manifest ', ' vendors ', ' common ', ' main ']
},
New Htmlwebpackplugin ({
  filename:path.join) (__dirname, '. /dist/entry.html '),//File Write path
  template:path.join (__dirname, ' ... /src/index.html '),//template file path
  inject:true,//insertion position
  chunks: [' manifest ', ' vendors ', ' common ', ' entry ']
} ,

It is necessary to manually specify the inserted chunks (synchronized) of each page, otherwise the files of other pages will be inserted into the current page. ④ Public JS extraction

In a single page, there is no common code to extract non-asynchronous JS files (node_modules) problem, in more than one page of our pages may be common APIs, configuration and other files, this time can be increased:

' Common ': {
  //Initial Settings extract common code in sync code
  chunks: ' initial ',
  //test: ' xxxx ', you can also use test to select which chunks code to extract
  NA Me: ' Common ',
  minsize:0,
  minchunks:2
}

Extract common code in synchronization code reference a Webpack-based persistent caching scheme Webpack issues vuejs-templates/webpack/issues
Author: tobethelight
Link: https://juejin.im/post/5ae925cff265da0ba76f89b7
Source: Nuggets
Copyright belongs to the author. Commercial reprint please contact the author to obtain authorization, non-commercial reprint please indicate the source.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.