SoFunction
Updated on 2025-04-06

vue-cli webpack configuration file analysis

I believe that vue users are not unfamiliar with vue-cli, and it can even be said that they are very familiar with it, but they may know very little about its webpack configuration.

After returning from the New Year, I took over the company's new project. The new project is a spa. Naturally, I thought of vue-cli scaffolding and then studied its webpack configuration. So, there are other contents.

Today's article has added some new versions of content based on the original, but it has not changed much in essence.

illustrate

This repository is a configuration analysis of vue-cli webpack, but it is actually just adding comments to the source code. For detailed analysis, you can start from the entry file mentioned later.

Analysis does not include files, because it detects npm and node versions and does not involve webpack, so no analysis is performed. At the same time, the code for the test part is not included. This analysis is only analyzed for webpack configurations in the development and production environment.

vue-cli version

2.8.1

Entrance

From the entrance to the development and production environment you can see.

 "scripts": {
  "dev": "node build/",
  "build": "node build/"
 }

Development Environment

The entry file for the development environment isbuild/


In this file, express is used as the backend framework and combined with some middleware about webpack to build a development environment.

// Configuration filevar config = require('../config')
// If the Node environment cannot determine that it is currently a dev / product environment// Use .NODE_ENV as the current environmentif (!.NODE_ENV) {
 .NODE_ENV = (.NODE_ENV)
}

// You can force the browser to open and jump to the plug-in for the specified url// /sindresorhus/opn
var opn = require('opn')
// Node comes with file path toolvar path = require('path')
// Express frameworkvar express = require('express')
var webpack = require('webpack')
// Test environment, the configuration used is the same as that used in the production environment// Non-test environment is the development environment, because this file is only used by the test environment and the development environmentvar proxyMiddleware = require('http-proxy-middleware')
var webpackConfig = .NODE_ENV === 'testing'
// Production environment configuration file ? require('./')
 // Development environment configuration file : require('./')

// The port number is the PORT parameter entered in the command line or the default value in the configuration filevar port =  || 
// Whether to automatically open the browser in the configuration filevar autoOpenBrowser = !!
// http proxy configuration in configuration file// /chimurai/http-proxy-middleware
var proxyTable = 

// Start the express servicevar app = express()
// Start webpack compilationvar compiler = webpack(webpackConfig)

// Plugins that can temporarily store compiled files into memory// /webpack/webpack-dev-middleware
var devMiddleware = require('webpack-dev-middleware')(compiler, {
 // Public path, same as webpack's publicPath publicPath: ,
 // Don't print quiet: true
})

// Hot-reload Hot reload plugin// /glenjamin/webpack-hot-middleware
var hotMiddleware = require('webpack-hot-middleware')(compiler, {
 log: () => {}
})
// Force refresh the browser after tml-webpack-plugin template('compilation', function (compilation) {
 ('html-webpack-plugin-after-emit', function (data, cb) {
  ({ action: 'reload' })
  cb()
 })
})

// Hang the request configuration in proxyTable on the startup express service(proxyTable).forEach(function (context) {
 var options = proxyTable[context]
 // If the data type of options is string, it means that only url is set. // So you need to set the url to the value of the target in the object if (typeof options === 'string') {
  options = { target: options }
 }
 (proxyMiddleware( || context, options))
})

// Use connect-history-api-fallback to match resources// If it does not match, you can redirect to the specified address// /bripkens/connect-history-api-fallback
(require('connect-history-api-fallback')())

// Hang the compiled files temporarily stored in memory on the express service(devMiddleware)

// Hang Hot-reload onto the express service(hotMiddleware)

// The static resource path of the static folder is splicedvar staticPath = (, )
// Static file service(staticPath, ('./static'))

var uri = 'http://localhost:' + port

// Print URL information after compilation is successful(function () {
 ('> Listening at ' + uri + '\n')
})

 = (port, function (err) {
 if (err) {
  (err)
  return
 }

 // If the browser is automatically opened and not the test environment, the browser will be opened automatically and jump to our development address if (autoOpenBrowser && .NODE_ENV !== 'testing') {
  opn(uri)
 }
})


A file is used in it, which is the configuration portal for webpack in the development environment.

// Tool function collectionvar utils = require('./utils')
var webpack = require('webpack')
 // Configuration filevar config = require('../config')
 // webpack configuration merge pluginvar merge = require('webpack-merge')
 // Basic webpac configurationvar baseWebpackConfig = require('./')
 // Automatically generate html and inject plugins into .html files // /ampedandwired/html-webpack-plugin
var HtmlWebpackPlugin = require('html-webpack-plugin')
 // webpack error message prompt plugin // /geowarin/friendly-errors-webpack-plugin
var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')

// Add Hol-reload hot reload client code to the corresponding entry of Hol-reload and package it together().forEach(function(name) {
 [name] = ['./build/dev-client'].concat([name])
})

 = merge(baseWebpackConfig, {
 module: {
  // styleLoaders
  rules: ({ sourceMap:  })
 },
 // The latest configuration is cheap-module-eval-source-map. Although cheap-module-eval-source-map is faster, its positioning is inaccurate // So, change to eval-source-map devtool: '#eval-source-map',
 plugins: [
  // definePlugin receives strings and inserts them into the code, so if you need them, you can write JS strings.  // Here, insert the appropriate environment  // /plugins/define-plugin/
  new ({
   '': 
  }),
  // When the HotModule plug-in changes the page, it will only repaint the corresponding page module, and will not repaint the entire html file.  // /glenjamin/webpack-hot-middleware#installation--usage
  new (),
  new (),
  // Create a file after injecting html code as an entry  // /ampedandwired/html-webpack-plugin
  new HtmlWebpackPlugin({
   filename: '',
   template: '',
   inject: true
  }),
  // webpack error message prompt plugin  new FriendlyErrorsPlugin()
 ]
})


Appearing in this file is the development environment and production environment, and even the test environment, the public webpack configuration of these environments. It can be said that this document is very important.

// Node comes with file path toolvar path = require('path')
// Tool function collectionvar utils = require('./utils')
 // Configuration filevar config = require('../config')
 // Tool function collectionvar vueLoaderConfig = require('./')

/**
  * Get the absolute path
  * @method resolve
  * @param {String} dir Path relative to this file
  * @return {String} Absolute path
  */
function resolve(dir) {
 return (__dirname, '..', dir)
}

 = {
 entry: {
  app: './src/'
 },
 output: {
  // Compile output static resource root path  path: ,
  // Compile output file name  filename: '[name].js',
  // The root path of the upper line path compiled and output under the official release environment  publicPath: .NODE_ENV === 'production' ?
    : 
 },
 resolve: {
  // Automatically complete extension  extensions: ['.js', '.vue', '.json'],
  // Path alias  alias: {
   // For example, import Vue from 'vue' will automatically search in 'vue/dist/'   'vue$': 'vue/dist/',
   '@': resolve('src'),
  }
 },
 module: {
  rules: [{
    // Review js and vue files    // /MoOx/eslint-loader
    test: /\.(js|vue)$/,
    loader: 'eslint-loader',
    // Indicates pre-processing    enforce: "pre",
    include: [resolve('src'), resolve('test')],
    options: {
     formatter: require('eslint-friendly-formatter')
    }
   },
   {
    // Process vue files    // /vuejs/vue-loader
    test: /\.vue$/,
    loader: 'vue-loader',
    options: vueLoaderConfig
   },
   {
    // Compile js    // /babel/babel-loader
    test: /\.js$/,
    loader: 'babel-loader',
    include: [resolve('src'), resolve('test')]
   },
   {
    // Process image files    // /webpack-contrib/url-loader
    test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
    loader: 'url-loader',
    query: {
     limit: 10000,
     name: ('img/[name].[hash:7].[ext]')
    }
   },
   {
    // Process font files    test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
    loader: 'url-loader',
    query: {
     limit: 10000,
     name: ('fonts/[name].[hash:7].[ext]')
    }
   }
  ]
 }
}

config/

This file is used in many files and is the main configuration file, including the path to the static file, whether to enable sourceMap, etc. Among them, it is divided into two parts: dev (configuration of development environment) and build (configuration of production environment).

// See the documentation for details: /webpack/var path = require('path')

 = {
 // production build: {
  // Build the environment  env: require('./'),
  // Build the output file  index: (__dirname, '../dist/'),
  // Build the output static resource path  assetsRoot: (__dirname, '../dist'),
  // Build the output secondary directory  assetsSubDirectory: 'static',
  // Build the root directory of the publish, which can be configured as a resource server domain name or CDN domain name  assetsPublicPath: '/',
  // Whether to enable cssSourceMap  productionSourceMap: true,
  // Gzip off by default as many popular static hosts such as
  // Surge or Netlify already gzip all static assets for you.
  // Before setting to `true`, make sure to:
  // npm install --save-dev compression-webpack-plugin
  // Turn gzip off by default, because many popular static resource hosts, such as Surge and Netlify, have enabled gzip for all static resources  productionGzip: false,
  // Need to use gzip compressed file extension  productionGzipExtensions: ['js', 'css'],
  // Run the build command with an extra argument to
  // View the bundle analyzer report after build finishes:
  // `npm run build --report`
  // Set to `true` or `false` to always turn it on or off
  // When running the "build" command line, add a parameter and you can refer to the package analysis report after the build is completed.  // true is on, false is off  bundleAnalyzerReport: .npm_config_report
 },
 // dev development environment dev: {
  // Build the environment  env: require('./'),
  // Port number  port: 3333,
  // Whether to automatically open the browser  autoOpenBrowser: true,
  assetsSubDirectory: 'static',
  // The root directory of the compiled and published can be configured as the resource server domain name or CDN domain name  assetsPublicPath: '/',
  // proxyTable proxy interface (can be cross-domain)  //Usage method: /webpack/  proxyTable: {},
  // CSS Sourcemaps off by default because relative paths are "buggy"
  // with this option, according to the CSS-Loader README
  // (/webpack/css-loader#sourcemaps)
  // In our experience, they generally work as expected,
  // just be aware of this issue when enabling this option.
  // By default, CSS Sourcemaps is turned off because using relative paths will cause an error.  // CSS-Loader README:/webpack/css-loader#sourcemaps
  cssSourceMap: false
 }
}


It is also a file that is used frequently, and this file contains three tool functions:

  • The path to generate static resources
  • Generate ExtractTextPlugin object or loader string
  • Generate the configuration of style-loader
// Node comes with file path toolvar path = require('path')
// Configuration filevar config = require('../config')
// Extract the plugin for css// /webpack-contrib/extract-text-webpack-plugin
var ExtractTextPlugin = require('extract-text-webpack-plugin')

/**
  * The path to generate static resources
  * @method assertsPath
  * @param {String} _path File path relative to static resource folder
  * @return {String} Static resource full path
  */
 = function (_path) {
 var assetsSubDirectory = .NODE_ENV === 'production'
  ? 
  : 
  // Like, but always interact in a posix-compatible way return (assetsSubDirectory, _path)
}

/**
  * Generate loaders configuration to process css
  * @method cssLoaders
  * @param {Object} options Generate configuration
  * option = {
  * // Whether to enable sourceMap
  * sourceMap: true,
  * // Whether to extract css
  * extract: true
  * }
  * @return {Object} handles loaders configuration object for css
  */
 = function (options) {
 options = options || {}

 var cssLoader = {
  loader: 'css-loader',
  options: {
   minimize: .NODE_ENV === 'production',
   sourceMap: 
  }
 }
 /**
   * Generate ExtractTextPlugin object or loader string
   * @method generateLoaders
   * @param {Array} loaders loader name array
   * @return {String|Object} ExtractTextPlugin object or loader string
   */
 function generateLoaders (loader, loaderOptions) {
  var loaders = [cssLoader]
  if (loader) {
   ({
    // For example, sass?indentedSyntax    //Previously add "-loader" to the ? number    loader: loader + '-loader',
    options: ({}, loaderOptions, {
     sourceMap: 
    })
   })
  }

  // When extract is true, extract css  // In production environment, the default is true  if () {
   return ({
    use: loaders,
    fallback: 'vue-style-loader'
   })
  } else {
   return ['vue-style-loader'].concat(loaders)
  }
 }

 // /vue-loader/en/configurations/
 return {
  css: generateLoaders(),
  postcss: generateLoaders(),
  less: generateLoaders('less'),
  sass: generateLoaders('sass', { indentedSyntax: true }),
  scss: generateLoaders('sass'),
  stylus: generateLoaders('stylus'),
  styl: generateLoaders('stylus')
 }
}

/**
  * Generate the configuration of style-loader
  * style-loader document: /webpack/style-loader
  * @method styleLoaders
  * @param {Object} options Generate configuration
  * option = {
  * // Whether to enable sourceMap
  * sourceMap: true,
  * // Whether to extract css
  * extract: true
  * }
  * @return {Array} style-loader configuration
  */
 = function (options) {
 var output = []
 var loaders = (options)
 for (var extension in loaders) {
  var loader = loaders[extension]
  ({
   test: new RegExp('\\.' + extension + '$'),
   use: loader
  })
 }
 return output
}

Production environment

The entry file of the development environment is build/ .


This file, for building a packaged file, will build the source code (compile, compress, etc.) and then package it.

// Set the current environment as a production environment.NODE_ENV = 'production'

// loading plugin// /sindresorhus/ora
var ora = require('ora')
// Tools that can execute `rm -rf` in node// /isaacs/rimraf
var rm = require('rimraf')
// Node comes with file path toolvar path = require('path')
// Output text with color at the terminal// /chalk/chalk
var chalk = require('chalk')
var webpack = require('webpack')
// Configuration filevar config = require('../config')
var webpackConfig = require('./')

// Show loading effect in the terminal and output promptvar spinner = ora('building for production...')
()

// Delete this folder (recursively delete)rm((, ), err => {
 if (err) throw err
 // Build webpack(webpackConfig, function (err, stats) {
  // Successful construction
  // Stop loading animation  ()
  if (err) throw err
  (({
   colors: true,
   modules: false,
   children: false,
   chunks: false,
   chunkModules: false
  }) + '\n\n')

  // Print prompt  ((' Build complete.\n'))
  ((
   ' Tip: built files are meant to be served over an HTTP server.\n' +
   ' Opening  over file:// won\'t work.\n'
  ))
 })
})


This file is the configuration portal for webpack in production environment. At the same time, it also relies on the aforementioned, and config/.

// Node comes with file path toolvar path = require('path')
// Tool function collectionvar utils = require('./utils')
var webpack = require('webpack')
// Configuration filevar config = require('../config')
// webpack configuration merge pluginvar merge = require('webpack-merge')
// Basic webpack configurationvar baseWebpackConfig = require('./')
// webpack plugin for copying files and folders// /kevlened/copy-webpack-plugin
var CopyWebpackPlugin = require('copy-webpack-plugin')
// Automatically generate html and inject plugins into .html files// /ampedandwired/html-webpack-plugin
var HtmlWebpackPlugin = require('html-webpack-plugin')
// Extract the plugin for css// /webpack-contrib/extract-text-webpack-plugin
var ExtractTextPlugin = require('extract-text-webpack-plugin')
// webpack optimizes compression and optimizes css plugin// /NMFR/optimize-css-assets-webpack-plugin
var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')

// If the current environment is a test environment, use the test environment// Otherwise, use the production environmentvar env = .NODE_ENV === 'testing'
 ? require('../config/')
 : 

var webpackConfig = merge(baseWebpackConfig, {
 module: {
  // styleLoaders
  rules: ({
   sourceMap: ,
   extract: true
  })
 },
 // Whether to enable sourceMap devtool:  ? '#source-map' : false,
 output: {
  // Compile output static resource root path  path: ,
  // Compile output file name  filename: ('js/[name].[chunkhash].js'),
  // File name of the output file with no output name specified  chunkFilename: ('js/[id].[chunkhash].js')
 },
 plugins: [
  // definePlugin receives strings and inserts them into the code, so if you need them, you can write JS strings.  // Here, insert the appropriate environment  // /vue-loader/en/workflow/
  new ({
   '': env
  }),
  // Compress js  new ({
   compress: {
    warnings: false
   },
   sourceMap: true
  }),
  // Extract css  new ExtractTextPlugin({
   filename: ('css/[name].[contenthash].css')
  }),
  // Compressed extracted css  // Can delete redundant code from different components  // Compress extracted CSS. We are using this plugin so that possible
  // duplicated CSS from different components can be deduped.
  new OptimizeCSSPlugin(),
  // Create a file after injecting html code as an entry  // /ampedandwired/html-webpack-plugin
  new HtmlWebpackPlugin({
   filename: .NODE_ENV === 'testing'
    ? ''
    : ,
   template: '',
   inject: true,
   minify: {
    removeComments: true,
    collapseWhitespace: true,
    removeAttributeQuotes: true
    // More options /kangax/html-minifier#options-quick-reference   },
   // Multiple chunks must be handled consistently through CommonsChunkPlugin   chunksSortMode: 'dependency'
  }),
  // Split public js to separate files  // /guides/code-splitting-libraries/#commonschunkplugin
  new ({
   name: 'vendor',
   minChunks: function (module, count) {
    // Any required module in node_modules is extracted to vendor    return (
      &&
     /\.js$/.test() &&
     (
      (__dirname, '../node_modules')
     ) === 0
    )
   }
  }),
  // Extract webpack runtime and module manifest to separate files to prevent public jsd hash from being updated when app packages are updated.  // extract webpack runtime and module manifest to its own file in order to
  // prevent vendor hash from being updated whenever app bundle is updated
  new ({
   name: 'manifest',
   chunks: ['vendor']
  }),
  // Copy static resources  // /kevlened/copy-webpack-plugin
  new CopyWebpackPlugin([
   {
    from: (__dirname, '../static'),
    to: ,
    ignore: ['.*']
   }
  ])
 ]
})

// When gzip is enabled, add compression-webpack-plugin plugin to webpack pluginsif () {
  // webpack compression plugin  // /webpack-contrib/compression-webpack-plugin
 var CompressionWebpackPlugin = require('compression-webpack-plugin')

 // Add the plugin below to it (
  new CompressionWebpackPlugin({
   asset: '[path].gz[query]',
   algorithm: 'gzip',
   test: new RegExp(
    '\\.(' +
    ('|') +
    ')$'
   ),
   threshold: 10240,
   minRatio: 0.8
  })
 )
}

// When opening package analysis, add webpack-bundle-analyzer plugin to webpack pluginsif () {
 // /th0r/webpack-bundle-analyzer
 var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
 (new BundleAnalyzerPlugin())
}

 = webpackConfig

other

If you think the code reading experience in segmentfault is not good, you can go to my github to clone the code.

vue-cli-webpack-analysis

Summarize

When I was studying webpack configuration this time, I followed the source code (a very stupid method), and then checked the functions and usage of the plug-ins used on github and webpack official websites. After this tossing, I have deepened my understanding of webpack.

The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.