Webpack – God like presence. No matter how many times write, meet again, is still the first. Sometimes I develop vUE projects and feel grateful for the great VUE – CLI. But, but, but… Not their own things, really do not want to toss. So, we have to go inside and cp them us. So, I spent two days, referring to some other people’s articles, looking up some official configuration, here is a little record.

This configuration parsing is based on the latest version of the Vue WebPack Template. However, I highly recommend that you stop reading my article and go through it sentence by sentence. And then look again. After all, it’s the collision of ideas that makes new discoveries.

Basic directory structure:

Config ├ ─ ─ dev. Env. Js / / dev environment variable configuration ├ ─ ─ index. The js / / dev and prod environment of some basic configuration └ ─ ─ the prod. The env. Js / / prod environment variable configuration build ├ ─ ─ build. Js / / ├── flag flag.png Flag Flag ── utils. ├─ webpack.base.conf.js // dev/prod Public Configuration ├── Vue -loader.conf.js // vue-loader.conf ├ ─ propack.prod.conf. Js // setup of the prod environmentCopy the code

Here we will analyze the source code in the following order:

config/index.js -> build/utils.js -> build/vue-loader.conf.js -> build/webpack.base.conf.js -> build/webpack.dev.conf.js -> build/webpack.prod.conf.js -> build/check-versions.js -> build/build.js

config/index.js: Configuration of some basic properties (we can change these configurations according to our own needs)

'use strict'
// This file is mainly a basic configuration for the development and production environments
const path = require('path')

module.exports = {
  // A basic configuration of the development environment
  dev: {
    // Compile the output secondary directory
    assetsSubDirectory: 'static'.// Compile and publish the root directory, can be configured as the resource server domain name or CDN domain name
    assetsPublicPath: '/'.// Interface that needs proxyTable proxy (cross-domain)
    proxyTable: {},

    // Access domain name at development time. You can set it yourself using environment variables.
    host: 'localhost'.// can be overwritten by process.env.HOST
    // Port at development time. This can be set using the environment variable PORT. If a port is occupied, an unused port is randomly assigned
    port: 8080.// Whether to open the browser automatically
    autoOpenBrowser: false.// Both of the following are ways for browsers to display errors
    // Whether to display error masking in the browser
    errorOverlay: true.// Whether to display error notifications
    notifyOnErrors: true.// This is an option of watchOptions for webpack-dev-servr that specifies how webpack checks files
    // Because WebPack uses the file system to get notification of file changes. In some cases, this may not work. For example, when using NFC,
    Vagrant also has many problems with this, in which case the poll option (polling to see if the file has changed) can be set to true
    // Or a specific value, specifying the specific period of file query.
    poll: false.// Whether to use the ESLint Loader to check code
    useEslint: true.// If set to true, esLint errors and warnings will be masked in browsers.
    showEslintErrorsInOverlay: false./** * Source Maps */

    // The format of source maps
    devtool: 'eval-source-map'.// Specifies whether to create a cache of the Source map by adding a query string after the file name
    cacheBusting: true.// Close the CSS source map
    cssSourceMap: false,},build: {
    // where the HTML file is generated
    index: path.resolve(__dirname, '.. /dist/index.html'),

    // The directory to compile the generated files
    assetsRoot: path.resolve(__dirname, '.. /dist'),
    // Directory of static files generated by compilation
    assetsSubDirectory: 'static'.// Compile and publish the root directory, can be configured as the resource server domain name or CDN domain name
    assetsPublicPath: '/'./** * Source Maps */

    productionSourceMap: true.devtool: '#source-map'.// Whether to enable gzip compression in the production environment
    productionGzip: false.// Suffix name of the file for which gzip compression is enabled
    productionGzipExtensions: ['js'.'css'].// If this option is true, a Bundler report will be generated in the browser after build
    bundleAnalyzerReport: process.env.npm_config_report
  }
}

Copy the code

build/utils.js: methods for generating CSS loaders and style loaders

'use strict'
// The nodejs path module is introduced to manipulate paths
const path = require('path')
// Import the template configuration file. What basic configuration does this file have
const config = require('.. /config')
// A plugin that extracts specific files, such as CSS files into a file
const ExtractTextPlugin = require('extract-text-webpack-plugin')
// Load the package.json file
const packageConfig = require('.. /package.json')

// Generate a secondary directory for compilation output
exports.assetsPath = function (_path) {
  const assetsSubDirectory = process.env.NODE_ENV === 'production'
    ? config.build.assetsSubDirectory
    : config.dev.assetsSubDirectory

  Posix is a cross-platform implementation of the path module (the path representation is different on different platforms)
  return path.posix.join(assetsSubDirectory, _path)
}

// To provide a unified generation method for different CSS preprocessors, that is, to handle the packaging problem of various CSS types uniformly.
// This is the CSS type for use in style in vue files
exports.cssLoaders = function (options) {
  options = options || {}

  // Package the CSS module
  const cssLoader = {
    loader: 'css-loader'.options: {
      sourceMap: options.sourceMap
    }
  }

  // Compile the postCSS module
  const postcssLoader = {
    // Use postCSs-loader to package postCSS modules
    loader: 'postcss-loader'.// Configure the source map
    options: {
      sourceMap: options.sourceMap
    }
  }

  // Create a loader string, used with the extract Text plug-in
  / * * * *@param {loader name} loader 
   * @param {Options configuration object for loader} loaderOptions 
   */
  function generateLoaders (loader, loaderOptions) {
    // usePostCSS to indicate whether postcss is used
    const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]

    // If the loader name is specified
    if (loader) {
      // Add the corresponding loader to the array of loaders
      An important point is that the loader in an array executes from right to left.
      loaders.push({
        // Name of the loader
        loader: loader + '-loader'.// The corresponding loader configuration object
        options: Object.assign({}, loaderOptions, {
          sourceMap: options.sourceMap
        })
      })
    }

    // If it is explicitly specified that static files need to be extracted
    / / ExtractTextPlugin. Extract ({}) to wrap our CSS processor.
    if (options.extract) {
      return ExtractTextPlugin.extract({
        use: loaders,
        // Fallback is a fallback option
        // WebPack by default compiles various CSS type files from right to left according to loaders in loaders. If all goes well, in loaders
        // After each loader runs, the CSS file will be imported into the specified file, if not successful, continue to use vue-style-loader to process
        / / CSS files
        fallback: 'vue-style-loader'})}else {
      // If there is no extract behavior, then use vue-style-loader to process CSS last
      return ['vue-style-loader'].concat(loaders)
    }
  }

  return {
    // css-loader
    css: generateLoaders(),
    // postcss-loader
    postcss: generateLoaders(),
    // less-loader
    less: generateLoaders('less'),
    // The options behind sass-loader indicate that sass uses indented render
    sass: generateLoaders('sass', { indentedSyntax: true }),
    // scss-loader
    scss: generateLoaders('sass'),
    // stylus-loader The stylus file has two suffixes: stylus and styl
    stylus: generateLoaders('stylus'),
    // stylus-loader
    styl: generateLoaders('stylus')}}// Use this function to create loader configurations for those separate style files.
exports.styleLoaders = function (options) {
  // Save the loader configuration variables
  const output = []
  // Get loaders for all CSS file types
  const loaders = exports.cssLoaders(options)

  for (const extension in loaders) {
    const loader = loaders[extension]
    // Generate the loader configuration
    output.push({
      test: new RegExp('\ \. + extension + '$'),
      use: loader
    })
  }

  return output
}

exports.createNotifierCallback = () = > {
  // Node-notifier is a cross-platform package that presents information in the form of browser-like notifications.
  const notifier = require('node-notifier')

  return (severity, errors) = > {
    // Display only error information
    if(severity ! = ='error') return

    const error = errors[0]
    const filename = error.file && error.file.split('! ').pop()

    // The contents of the error message to display
    notifier.notify({
      // The title of the notification
      title: packageConfig.name,
      // The body of the notification
      message: severity + ':' + error.name,
      / / subtitle
      subtitle: filename || ' '.// Notification display icon
      icon: path.join(__dirname, 'logo.png')}}}Copy the code

build/vue-loader.conf.js: Basic configurations of vue-loader

'use strict'
const utils = require('./utils')
const config = require('.. /config')
// Set the production environment
const isProduction = process.env.NODE_ENV === 'production'
// Import different Source map profiles for different environments
const sourceMapEnabled = isProduction
  ? config.build.productionSourceMap
  : config.dev.cssSourceMap

module.exports = {
  // CSS Loader configuration in vue file
  loaders: utils.cssLoaders({
    sourceMap: sourceMapEnabled,
    // In production, the CSS file is extracted into a separate file
    extract: isProduction
  }),
  // CSS source map file configuration
  cssSourceMap: sourceMapEnabled,
  // CSS source map file cache control variables
  cacheBusting: config.dev.cacheBusting,
  transformToRequire: {
    video: ['src'.'poster'].source: 'src'.img: 'src'.image: 'xlink:href'}}Copy the code

build/weback.base.conf.js: common configuration in dev and PROd environments

'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('.. /config')
const vueLoaderConfig = require('./vue-loader.conf')
// Generates an absolute path relative to the root directory
function resolve (dir) {
  return path.join(__dirname, '.. ', dir)
}

// esLint rules
const createLintingRule = () = > ({
  // Eslint checks.js and.vue files
  test: /\.(js|vue)$/./ / use eslint - loader
  loader: 'eslint-loader'.// Enforce may be pre and post. Pre is similar to the preLoader configuration in webpack@1.
  // Post and postLoader in v1 have similar meanings. Indicates the call time of loader
  Call this rule for code style checking before calling any other loader
  enforce: 'pre'.// Where the directory for files to be checked by ESLint exists
  include: [resolve('src'), resolve('test')].// Options to specify during eslint-loader configuration
  options: {
    // Check the file style formatter, where the third-party ESlint-friendly-formatter is used
    formatter: require('eslint-friendly-formatter'),
    // Whether eslint outputs warnings
    emitWarning: !config.dev.showEslintErrorsInOverlay
  }
})

// The following is the basic configuration information for WebPack (which can be immediately made common to both development and production environments)
module.exports = {
  // The root directory where webpack parses the file (if you put webpack.config.js) under the root directory of the project, this configuration can be omitted
  context: path.resolve(__dirname, '.. / '),
  // Specify the entry file for the project
  entry: {
    app: './src/main.js'
  },
  // Project output configuration
  output: {
    // When the project is built, the generated file is stored in the path (here is the path.. /dist)
    path: config.build.assetsRoot,
    // The name of the generated file
    filename: '[name].js'.// Output directory of parsed files, url relative to HTML page (generated HTML files, static files such as CSS and JS URL prefix)
    publicPath: process.env.NODE_ENV === 'production'
      ? config.build.assetsPublicPath
      : config.dev.assetsPublicPath
  },
  // Configure some options for module parsing
  resolve: {
    // Specify which types of files can be referenced without the suffix
    extensions: ['.js'.'.vue'.'.json'].// Alias, which can be used when importing files
    alias: {
      'vue$': 'vue/dist/vue.esm.js'.// You can import files in the SRC folder with the @ symbol
      The '@': resolve('src'),}},// Here are the specific configurations for specific modules
  // The following configuration syntax uses version >= @2
  module: {
    // Rules is an array where each element is an object that is configured for a specific type of file.
    rules: [
      //.vue file configuration
      {
        // This property is a regular expression used to match files. The match here is the.vue file
        test: /\.vue$/.// Specify the loader name for this type of file
        loader: 'vue-loader'.// Specific configuration for this loader
        For the previous analysis, this configuration object contains the configuration of various CSS type files, CSS Source map configuration, and some transform configuration
        options: vueLoaderConfig
      },
      {
        //.js file configuration
        test: /\.js$/.// Babel-loader is used for processing js files. No specific compilation rules are specified here, and babel-loader will automatically
        The Babel configuration in the. Babelrc directory is used to compile js files
        {/ * * * * / / use the preset "presets" : [/ / Babel - preset - env: ["env", {// modules set to false, does not convert module "modules": false}], // babel-stage-2: preset () Stage2 syntax "stage-2"], // babel-plugin-transform-runtime: // To support new apis, introduce babel-polyfill "plugins": ["transform-runtime"]} */
        loader: 'babel-loader'.// Specify the path to the file to compile
        // Only files in the SRC and test folders are compiled
        include: [resolve('src'), resolve('test')]}, {// Configure the image resource to compile
        // Specify the type of file
        test: /\.(png|jpe? g|gif|svg)(\? . *)? $/.// Use url-loader to compile file resources
        loader: 'url-loader'.// Url-loader configuration options
        options: {
          A dataUrl is returned if the file size is less than 10000 bytes (10KB)
          limit: 10000.// Save path and suffix of the generated file
          name: utils.assetsPath('img/[name].[hash:7].[ext]')}}, {// Package and compile the video file
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\? . *)? $/,
        loader: 'url-loader'.options: {
          limit: 10000.name: utils.assetsPath('media/[name].[hash:7].[ext]')}}, {// Package the font file
        test: /\.(woff2? |eot|ttf|otf)(\? . *)? $/,
        loader: 'url-loader'.options: {
          limit: 10000.name: utils.assetsPath('fonts/[name].[hash:7].[ext]'}}]},// These options are used to polyfill or mock certain Node.js global variables and modules.
  // This enables the code originally written for NodeJS to run on the browser side
  node: {
    // This configuration is an object in which each property is the name of a nodeJS global variable or module
    // prevent webpack from injecting useless setImmediate polyfill because Vue
    // source contains it (although only uses it if it's native).
    // false means that nothing is supplied. If you retrieve the code for this object, a ReferenceError may be raised because you can't retrieve the object
    setImmediate: false.// prevent webpack from injecting mocks to Node native modules
    // that does not make sense for the client
    // Set to empty to provide an empty object
    dgram: 'empty'.fs: 'empty'.net: 'empty'.tls: 'empty'.child_process: 'empty'}}Copy the code

build/weboack.dev.conf.js: Configuration of the Dev environment

'use strict'
// We will introduce some utility methods. We need to go to the util file to see what the corresponding utility methods are
const utils = require('./utils')
// Introduce the Webpack module
const webpack = require('webpack')
// Import the configuration file
// This configuration file contains some basic configurations for the dev and Production environments
const config = require('.. /config')
// Introduce the webpack-merge module. This module is used to combine multiple WebPack configurations into a single configuration, which overrides the previous configuration.
const merge = require('webpack-merge')
// Introduces the basic Settings for Webpack, which contains some common configurations for both the development and production environments
const baseWebpackConfig = require('./webpack.base.conf')
// A plug-in for generating HTML files
const HtmlWebpackPlugin = require('html-webpack-plugin')
// This plugin can better see errors and warnings when WebPack is running on the terminal. Can improve the development experience.
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
// Find an unused port
const portfinder = require('portfinder')

// Get the host environment variable, which is used to configure the development environment domain name
const HOST = process.env.HOST
// Get the POST environment variable, which is used to configure the port number for the development environment
const PORT = process.env.PORT && Number(process.env.PORT)

// Complete configuration file for the development environment,
const devWebpackConfig = merge(baseWebpackConfig, {
  module: {
    // Add loader configuration for those separate CSS type files (styles not written in the style tag of vue files)
    rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true})},// The development environment uses source map in 'eval-source-map' mode
  // Because of the speed
  devtool: config.dev.devtool,

  // these devServer options should be customized in /config/index.js
  // The following is the basic configuration of the webpack-dev-server option. This configuration information can be found in /config/index.js
  // Customize the configuration in the file.
  devServer: {
    // Used to configure the log level displayed in the development tool console
    // Note that this is not a configuration for errors and warnings from the bundle, but for messages before it is generated
    clientLogLevel: 'warning'.// indicates that any 404 response needs to be replaced with index.html when using HTML5's history API
    historyApiFallback: true.// Enable webPack's hot replace feature
    hot: true.// All services need to use gzip compression
    Content-encoding :gzip Response header content-encoding :gzip response header content-encoding :gzip response header
    compress: true.// Specify the use of a host. The default is localhost
    // If you want external server access (through our computer IP address and port number to access our application)
    // You can specify 0.0.0.0
    host: HOST || config.dev.host,
    // Specify the port number to listen for requests
    port: PORT || config.dev.port,
    // Whether to open the browser automatically
    open: config.dev.autoOpenBrowser,
    // Do you want to display a full-screen mask in the browser to show error messages when compiling errors
    overlay: config.dev.errorOverlay
    // Displays only error information but no warning information
    // If both want to be displayed, set both items to true
      ? { warnings: false.errors: true }
      // Set to false to display nothing
      : false.// Specify the root directory of webpack-dev-server, where all files are directly accessible through the browser
      // It is recommended to set output.publicPath to the same value
    publicPath: config.dev.assetsPublicPath,
    // Configure the proxy so that we can access some interfaces across domains
    // The interface we access, if configured for this option, will forward our request through a proxy server
    proxy: config.dev.proxyTable,
    // With quiet enabled, nothing is printed to the console except the initial startup information. This also means that errors or warnings from Webpack are not visible on the console.
    quiet: true.// necessary for FriendlyErrorsPlugin
    // Control options related to monitoring files.
    watchOptions: {
      // If this option is true, changes to our files will be checked by polling, which is inefficient
      poll: config.dev.poll,
    }
  },
  plugins: [
    // Create a global variable that can be configured at compile time
    new webpack.DefinePlugin({
      'process.env': require('.. /config/dev.env')}),// Enable the hot replacement module
    // Remember, we should never use HMR in production environment again
    new webpack.HotModuleReplacementPlugin(),
    // The main function of this plugin is to return the name of the updated file, not the id of the file, during hot loading
    new webpack.NamedModulesPlugin(),
    // Use this plugin to skip the output phase if a compilation error occurs, thus ensuring that the output resource does not contain errors.
    new webpack.NoEmitOnErrorsPlugin(),

    // This plugin basically generates an HTML file
    new HtmlWebpackPlugin({
      // The name of the generated HTML file
      filename: 'index.html'.// The name of the template to use
      template: 'index.html'.// Insert all static files at the end of the body file
      inject: true})]})module.exports = new Promise((resolve, reject) = > {
  portfinder.basePort = process.env.PORT || config.dev.port
  // This method of getting a port returns a promise
  portfinder.getPort((err, port) = > {
    if (err) {
      reject(err)
    } else {
      // Set the obtained PORT number to the value of the environment variable PORT
      process.env.PORT = port
      // Resets the port value of webpack-dev-server
      devWebpackConfig.devServer.port = port

      // Add FriendlyErrorsPlugin to the webPack configuration file
      devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
        // Output information when compiling successfully
        compilationSuccessInfo: {
          messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],},/ / when the compiler error, according to the config. Dev. NotifyOnErrors to determine whether to need to display the error notification box in the upper right corner of the desktop
        onErrors: config.dev.notifyOnErrors
        ? utils.createNotifierCallback()
        : undefined
      }))
      // resolve our config file
      resolve(devWebpackConfig)
    }
  })
})
Copy the code

build/webpack.prod.conf.js: Basic configuration of the PROD environment

'use strict'
// Introduce the path module
const path = require('path')
// Introduce tool methods
const utils = require('./utils')
// Introduce the Webpack module
const webpack = require('webpack')
// Introduce the basic configuration
const config = require('.. /config')
// Introduce the webpack-merge module
const merge = require('webpack-merge')
// Introduce configurations common to both development and production environments
const baseWebpackConfig = require('./webpack.base.conf')
// Introduce the copy-webpack-plugin module
// This module is mainly used to copy files and folders in webpack
const CopyWebpackPlugin = require('copy-webpack-plugin')
// Introduce the htmL-webpack-plugin
// This plugin is mainly used to generate HTML files based on templates
const HtmlWebpackPlugin = require('html-webpack-plugin')
// Introduce extract-text-webpack-plugin
// This plugin is mainly used to move all chunks in the entry into a separate CSS file
const ExtractTextPlugin = require('extract-text-webpack-plugin')
// Import the optimize- CSS -assets-webpack-plugin
// This plugin is mainly used to compress CSS modules
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
// Introduce uglifyjs-webpack-plugin
// This plugin is mainly used to compress JS files
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
// Introduce some basic variables for the production environment
const env = require('.. /config/prod.env')

// Merge the common and production-specific configurations and return a WebPack configuration file for the production environment
const webpackConfig = merge(baseWebpackConfig, {
  // Some Loader configurations for production environments
  module: {
    rules: utils.styleLoaders({
      sourceMap: config.build.productionSourceMap,
      // Use the extract option in production, which pulls the CSS code from Thunk into a separate CSS file
      extract: true.usePostCSS: true})},// Configure the form of source map to be used in the production environment. In this case, the production environment uses the form # Source Map
  devtool: config.build.productionSourceMap ? config.build.devtool : false.output: {
    // The directory where the files generated by build are stored
    path: config.build.assetsRoot,
    // The name of the file after build
    // where [name] and [chunkhash] are placeholders
    // Where [name] refers to the module name
    // [chunkhash] Chunk hash character string, 20 characters in length
    filename: utils.assetsPath('js/[name].[chunkhash].js'),
    // [id] is also a placeholder for the module identifier.
    chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')},plugins: [
    // http://vuejs.github.io/vue-loader/en/workflow/production.html
    new webpack.DefinePlugin({
      'process.env': env
    }),
    // A plug-in to compress javascript
    new UglifyJsPlugin({
      // Some basic configuration for compressing JS
      uglifyOptions: {
        // Configure compression behavior
        compress: {
          // Displays warning messages when deleting unused variables, etc. The default is false
          warnings: false}},// Use the source map to map the location of the error message to the module (this will slow down compilation)
      // Do not use cheap source-map
      sourceMap: config.build.productionSourceMap,
      // Use multi-process parallel running and file caching to speed up builds
      parallel: true
    }),

    // Extract the CSS file into a separate file
    new ExtractTextPlugin({
      // Where the CSS file is stored after extraction
      // Where [name] and [contenthash] are placeholders
      // [name] indicates the module name
      // [contenthash] Hash generated based on the extracted file contents
      filename: utils.assetsPath('css/[name].[contenthash].css'),
      
      // Extract CSS content from all additional chunks
      // (by default, it is only extracted from the initial chunk)
      / / when using CommonsChunkPlugin and extraction in public the chunk chunk (from ExtractTextPlugin. Extract)
      // This option needs to be set to true
      allChunks: false,}).// duplicated CSS from different components can be deduped.
    // Use this plugin to compress CSS, mainly because the same CSS can be removed from different components
    new OptimizeCSSPlugin({
      // All configuration for this option is passed to the cssProcessor
      // The cssProcessor uses these options to determine the behavior of compression
      cssProcessorOptions: config.build.productionSourceMap
      // Safe means "safe". Please leave a message to let us know...
        ? { safe: true.map: { inline: false}}, {safe: true}}),// Create an HTML file
    new HtmlWebpackPlugin({
      // The name of the generated file
      filename: config.build.index,
      // The name of the template to use
      template: 'index.html'.// Place the script and link tags at the bottom of the body
      inject: true.// Configure HTML compression behavior
      minify: {
        // Remove comments
        removeComments: true.// Remove whitespace and newlines
        collapseWhitespace: true.// Remove quotes and empty attributes from attributes as much as possible
        removeAttributeQuotes: true
        // more options:
        // https://github.com/kangax/html-minifier#options-quick-reference
      },
      // Control the order of the chunks
      // it can also be a function that defines its own collation rules
      chunksSortMode: 'dependency'
    }),
    // keep module.id stable when vender modules does not change
    // Generate a four-digit hash for the module ID based on the relative path of the module
    new webpack.HashedModuleIdsPlugin(),

    // Every module webPack2 processes is wrapped with a function
    // The problem with this is that it reduces the efficiency of javascript execution in browsers, mainly because closure functions slow down the parsing speed of the JS engine.
    // In webpack3, you can use the following plugin to connect some related modules,
    // Put it in a closure function to speed up JS execution by reducing the number of closure functions.
    new webpack.optimize.ModuleConcatenationPlugin(),

    // This plugin is used to extract the public modules of multi-entry chunks
    // By extracting the public modules, the resultant file can be loaded once at the beginning
    // It is then cached for later use, which increases speed.
    new webpack.optimize.CommonsChunkPlugin({
      // This is the name of Common Chunk
      name: 'vendor'.// Extract all files imported from mnode_modules into vendor
      minChunks (module) {
      
        return (
          module.resource &&
          /\.js$/.test(module.resource) &&
          module.resource.indexOf(
            path.join(__dirname, '.. /node_modules'= = =))0)}}),// In order to remove third-party dependencies from the project, the official documentation recommends using this plug-in. When we actually use it in the project,
    // Find that once you change the code in app.js, the vendor.js hash will also change, so the next time you go online,
    // The user still needs to download vendor.js and app.js again -- thus losing the point of caching. So the second new is to solve this problem
    Reference: / / https://github.com/DDFE/DDFE-blog/issues/10
    new webpack.optimize.CommonsChunkPlugin({
      name: 'manifest'.minChunks: Infinity
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'app'.async: 'vendor-async'.children: true.minChunks: 3
    }),

    // copy custom static assets
    // Copy static resources into the build folder
    new CopyWebpackPlugin([
      {
        // Define the source directory of the resource to be copied
        from: path.resolve(__dirname, '.. /static'),
        // Define the destination directory of the resource to copy
        to: config.build.assetsSubDirectory,
        // Ignore copying the specified file. Fuzzy matching can be used
        ignore: ['*']}])]})if (config.build.productionGzip) {
  // If gzip is enabled in the production environment
  const CompressionWebpackPlugin = require('compression-webpack-plugin')

  webpackConfig.plugins.push(
    new CompressionWebpackPlugin({
      // Name of the target resource
      // [path] will be replaced with the original resource path
      // [query] is replaced with the original query string
      asset: '[path].gz[query]'./ / gzip algorithm
      // This option can be configured for each algorithm in the zlib module
      // Also (buffer, cb) => cb(buffer)
      algorithm: 'gzip'.// Process all resources that match this regular expression
      test: new RegExp(
        '\ \. (' +
        config.build.productionGzipExtensions.join('|') +
        '$'
      ),
      // Only resources larger than this value are processed
      threshold: 10240.// Only resources with compression rates lower than this value will be processed
      minRatio: 0.8}}))if (config.build.bundleAnalyzerReport) {
  // If you need to generate a bundle report, you need to use the plug-in below
  const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
  webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}

module.exports = webpackConfig
Copy the code

build/check-versions.js: Check the version of NPM and Node

'use strict'
// Display different styles for different fonts on the terminal
const chalk = require('chalk')
// Parse the version of NPM package
const semver = require('semver')
// Import package.json file
const packageConfig = require('.. /package.json')
// Node version of uninx shell command
const shell = require('shelljs')

// The function that executes the command
function exec (cmd) {
  return require('child_process').execSync(cmd).toString().trim()
}

const versionRequirements = [
  {
    name: 'node'.// Node version
    // process.version is the node version
    / / semver. Clean (' v8.8.0 ') = > 8.8.0
    currentVersion: semver.clean(process.version),
    // The range of node versions defined in package.json
    versionRequirement: packageConfig.engines.node
  }
]

// equivalent to which NPM
if (shell.which('npm')) {
  // If NPM exists
  versionRequirements.push({
    name: 'npm'.// Check the NPM version => 5.4.2
    currentVersion: exec('npm --version'),
    // The version of NPM defined in package.json
    versionRequirement: packageConfig.engines.npm
  })
}

module.exports = function () {
  const warnings = []

  for (let i = 0; i < versionRequirements.length; i++) {
    const mod = versionRequirements[i]

    // semver.distribution () for comparison between versions
    if(! semver.satisfies(mod.currentVersion, mod.versionRequirement)) {If the existing NPM or Node version is lower than the defined version, a warning is generated
      warnings.push(mod.name + ':' +
        chalk.red(mod.currentVersion) + ' should be ' +
        chalk.green(mod.versionRequirement)
      )
    }
  }

  if (warnings.length) {
    console.log(' ')
    console.log(chalk.yellow('To use this template, you must update following to modules:'))
    console.log()

    for (let i = 0; i < warnings.length; i++) {
      const warning = warnings[i]
      console.log(' ' + warning)
    }

    console.log()
    // Exit the program
    process.exit(1)}}Copy the code

build/build.js: build a project

'use strict'
// Check NPM and Node versions
require('./check-versions') ()// Set the value of the environment variable NODE_ENV to production
process.env.NODE_ENV = 'production'

// Terminal spinner
const ora = require('ora')
// Node.js rm -rf
const rm = require('rimraf')
// Introduce the path module
const path = require('path')
// Introduce the display terminal color module
const chalk = require('chalk')
// Introduce the Webpack module
const webpack = require('webpack')
// Import the basic configuration file
const config = require('.. /config')
// Import webPack configuration files in production environment
const webpackConfig = require('./webpack.prod.conf')

// 
const spinner = ora('building for production... ')
spinner.start()

// Delete the files in the package target directory
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err= > {
  if (err) throw err
  // Do the packing
  webpack(webpackConfig, (err, stats) = > {
    // The package is complete
    spinner.stop()
    if (err) throw err
    // Outputs the status of packaging
    process.stdout.write(stats.toString({
      colors: true.modules: false.children: false.chunks: false.chunkModules: false
    }) + '\n\n')

    // If there is an error in packaging
    if (stats.hasErrors()) {
      console.log(chalk.red(' Build failed with errors.\n'))
      process.exit(1)}// The package is complete
    console.log(chalk.cyan(' Build complete.\n'))
    console.log(chalk.yellow(
      ' Tip: built files are meant to be served over an HTTP server.\n' +
      ' Opening index.html over file:// won\'t work.\n'))})})Copy the code

Reprinted in: Understand vue- CLI vue Webpack Template configuration