Webpack profile

Webpack is actually a static module packaging tool

When WebPack works on a project, it recursively builds a Dependency graph of each module the application needs, and then packages all of those modules into one or more bundles.

Principle of packaging

  • Identification entry file
  • Identify module dependencies layer by layer. Commonjs, AMD, or ES6 imports are analyzed by WebPack. To get code dependencies)
  • What WebPack does is analyze the code. Transform code, compile code, output code
  • The result is packaged code

Package debug command

npm run dev

npm run build
Copy the code

packages.json

."scripts": {
  "dev_def": "webpack-dev-server --inline --public --config build/dev.js"."dev": "nodemon --watch config/index.js --exec \"webpack-dev-server --inline --public --config build/dev.js\""."start": "npm run dev"."build": "cross-env NODE_ENV=production node build/build.js"}...Copy the code

webpack-dev-server

Is a lightweight server, after modifying the source file, automatically refresh the page to synchronize the changes to the page

webpack-dev-server --inline --public --config build/dev.js
Copy the code
  • Inline mode: A script will be inserted into the package to handle real-time reloads, and the build message will be displayed in the browser console.
module.exports = {
  //...
  devServer: {
    inline: true}};Copy the code
  • [–public XXX] When using inline mode and proxying dev-server, the inline client script does not always know where to connect. It will try to guess window.location based on the URL of the server, but will need to use it if it fails
  • [–config XXX] Specifies the configuration file
  • [–progress] Prints the running progress to the console.

nodemon

It will monitor the files in the project and automatically restart the application once any changes are found in the files

  • 【–watch XXX 】 Monitors specified files or directories
  • 【–exec XXX 】 execute the specified command
nodemon --watch config/index.js --exec \"webpack-dev-server --inline --public --config build/dev.js\"
Copy the code

Use nodemon to monitor the config/index.js file. If there is any change, run the webpack-dev-server –inline –public –config build/dev.js command again

The [webpack-dev-server –inline –public –config build/dev.js] command has the hot update function for the project itself, but the change of the webpack configuration file does not take effect. With Nodemon, the service is restarted when the WebPack configuration file is modified, which is an automatic supplement

cross-env

Addresses cross-platform setup and scripting using environment variables, such as variable names and paths

  • Cross -env NODE_ENV=production smoothen cross-platform environment variable Settings

The basic configuration

Module.exports = {// exports file entry: {app:'./src/js/index.js'}, // Where to export the bundles it creates: {filename:'[name].bundle.js',
    path: path.resolve(__dirname, 'dist'),
    publicPath: '/'// Make sure file resources are properly accessed at http://localhost:3000}, // developer toolssource-map
  devtool: 'inline-source-map'// Create devServer: {contentBase:'./dist',
    hot: trueNew CleanWebpackPlugin(['dist'// new HtmlWebpackPlugin({title:'Output Management'}), / / in order to more easily view to repair (patch) rely on new webpack. NamedModulesPlugin (), / / hot update module new webpack. HotModuleReplacementPlugin ()], / / environment mode:"development"// loader configuration module: {rules: [{test: /\.css$/,
        use: [
          'style-loader'.'css-loader'] {},test: /\.(png|svg|jpg|gif)$/,
        use: [
          'file-loader'}]}}Copy the code

__dirname: absolute path of the current file folder

Entry (Entry file configuration)

Single entry syntax (short)

entry: './path/to/my/entry/file.js'// Or entry: {main:'./path/to/my/entry/file.js'
}
Copy the code

Multi-page applications

entry: {
  pageOne: './src/pageOne/index.js',
  pageTwo: './src/pageTwo/index.js',
  pageThree: './src/pageThree/index.js'
}
Copy the code

Note: Written before Webpack (not recommended)

entry:{
  vendor:[resolve('src/lib/polyfill.js'), 'vue'.'vue-router'], // do not recommend app: resolve('src/main.ts')}Copy the code

In versions prior to Webpack4, it was common to add a vendor as a separate entry point to compile it into a separate file vendor (combined with CommonsChunkPlugin)

This is discouraged in WebPack 4. Instead, the optimization.splitchunks option is responsible for separating vendor and application modules and creating separate files. Do not create an entry for a vendor or something else that is not a starting point for execution.

Output (Output file configuration)

output: {
  filename: '[name].bundle.js',
  chunkFilename: [name].min.js,
  path: path.resolve(__dirname, 'dist'),
  publicPath: '/'// Make sure file resources are properly accessed at http://localhost:3000}Copy the code
  • Filename: indicates the output filename
  • ChunkFilename: This option determines the name of the non-entry file
  • Path: indicates the destination path of all output files
  • PublicPath: specifies the directory referenced by the resource file, the file after build, and the prefix of the resource reference path

Devtool (Debugging tool: File Mapping)

// dev
devtool: 'eval-source-map'

// prod
devtool: 'source-map'
Copy the code

Key words revealed:

The keyword meaning
eval At packaging time, generated bundle.js files, modules are wrapped in eval, followed by sourceUrl, pointing to the original file
source-map This configuration generates a.map file that maps to the original file and is used to locate the original code during debugging
cheap Low consumption packaging, which is when the map file is packaged, does not store the column position of the original code, only contains the row position, so this explains the explanation behind the official image (row only).
. .

devServer

devServer: {
  compress: true,
  port: 9000,
  hot: true,
  https: true,
  overlay: {
    warnings: false,
    errors: true
  },
  publicPath: '/platform/redapply/'
}
Copy the code
  • Compress: Enables gzip compression
  • Port: the port number
  • Hot: Indicates whether to enable the Hot Module Replacement feature
  • HTTPS: you can use a self-signed certificate, can also customize signing certificate | Boolean, object
  • Overlay: full screen compile errors or warnings on the browser | Boolean, object
  • PublicPath: the packaged file will be deployed to the path corresponding to the configuration. http://localhost:8080/platform/redapply/index.html

Mode (tells Webpack to use its built-in optimizations accordingly)

// dev
mode: 'development'

// build
mode: 'production'
Copy the code

Plugins

plugins: [
  new webpack.DefinePlugin({
    'process.env': {
       NODE_ENV: '"production"'}}),]Copy the code

Module. rules (Loader configuration)

module: {
  rules: [
    {
      test: /\.css$/,
      use: [
        'style-loader'.'css-loader'] {},test: /\.(png|svg|jpg|gif)$/,
      use: [
        'file-loader']]}}Copy the code

The execution sequence of the Loader is from back to front

Common Project Configuration

Resolve (resolve)

resolve: {
  extensions: ['.js'.'.ts'.'.vue'.'.json'].alias: {
    '@lib': resolve('src/lib'),
    '@models': resolve('build/models'),
    '@components': resolve('src/components'),
    '@data': resolve('src/data'),
    The '@': resolve('src')}}Copy the code
  • Extensions that parse path default file names (try in order)
  • Alias User-defined path symbol definition

Preloaded file

For example, define some common SCSS files. In order not to introduce this file on every page. We can set file preloading

module: {
  rules: [
    ...
    {
      test: /\.sass|scss|css$/,
      use: [
        ...
        {
          loader: 'sass-resources-loader',
          options: {
            resources: [
              path.resolve(__dirname, '.. /src/assets/css/vars.scss'),
              path.resolve(__dirname, '.. /src/assets/css/common.scss']}}]}Copy the code

Optimization (optimize configuration items, configure at build)

optimization: {
    minimize: true// The default istrueThe effect is to compress js code. Minimizer: [// New TerserPlugin(), new OptimizeCSSAssetsPlugin({})], runtimeChunk: {// Default isfalseTo extract the common code block at the time of shipment. name:'manifest'
    },
    splitChunks:{
      chunks: 'all', // You must choose one of three:"initial" | "all"| (recommended)"async"(async by default) minSize: 30000, // Minimum number of bytes generated chunks, 30000 minChunks: 1, // Minimum number of times referenced maxAsyncRequests: // maxInitialRequests: 3, // maxInitialRequests: 3true, // the name of the packaged chunks cacheGroups: {// the cache configuration common: {name:'common'// chunks to cache:'initial', // You must choose one of three:"initial" | "all" | "async"Priority: 11, enforce:true,
          reuseExistingChunk: true, // You can set whether to reuse the chunktest: / / / / node_modules / [\] (vue | Babel \ - polyfill | mint \ - UI) /}, vendor: {/ / entry name defined in the key for the entry name:'vendor'// chunks to cache:'initial', // You must choose one of three:"initial" | "all" | "async"Priority: 10, enforce:true,
          reuseExistingChunk: true, // You can set whether to reuse the chunktest: /node_modules\/(.*)\.js/
        },
        styles: {
          name: 'styles'.test: /\.(scss|css)$/,
          chunks: 'all',
          minChunks: 1,
          reuseExistingChunk: true,
          enforce: true}}}}Copy the code

runtimeChunk

The default is false, and the common code block is extracted at the time of shipment

What is runtime?

JS in the browser can call the browser provided by the API, such as the window object, DOM related API. These interfaces are not provided by the V8 engine, they exist in the browser. So in simple terms, these related external interfaces can be called by JS at RunTime, as well as JS Event loops and Callback queues, called RunTime. Some places also consider the core lib library used by JS as part of the RunTime.

The chunk runtime

The environment (method) on which chunk is executed

splitChunks

chunks

function (chunk) | string

This indicates which blocks will be selected for optimization

string:

  • Initial-entry chunk. Files imported asynchronously are not processed
  • Async – asynchronous chunk, only for files imported asynchronously (personal understanding)
  • All-all Chunk

function:

splitChunks: {
  chunks (chunk) {
    // exclude `my-excluded-chunk`
    returnchunk.name ! = ='my-excluded-chunk'; }}Copy the code

cacheGroups

The cache group can inherit and/or override any option splitChunks.*; To disable any default cache group, set it to false.

  • Priority: a module can belong to multiple cache groups and will be allocated to a chunk with a higher priority
  • ReuseExistingChunk indicates that an existing chunk can be used, that is, if a conditional chunk already exists, the existing chunk is used instead of creating a new chunk
  • Enforce minSize, minChunks, and maxInitialRequests options for quickly creating chunks
  • Test Indicates the rule of the cache group, which indicates that the matches are added to the current cache group
optimization: {
  splitChunks: {
    chunks: 'async',
    minSize: 30000,
    minChunks: 1,
    maxAsyncRequests: 3,
    maxInitialRequests: 3,
    name: true,
    cacheGroups: {
      common: {
        name: 'common',
        chunks: 'initial',
        priority: 11,
        enforce: true,
        reuseExistingChunk: true, // You can set whether to reuse the chunktest: /[\/|\\]node_modules[\/|\\](vue|babel\-polyfill|mint\-ui)/
      },
      vendor: {
        name: "vendor",
        chunks: "initial",
        priority: 10,
        test: /[\/|\\]node_modules[\/|\\](.*)\.js/
      },
      styles: {
        name: 'styles'.test: /\.(scss|css|less)$/,
        chunks: 'initial',
        minChunks: 1,
        reuseExistingChunk: true,
        enforce: true}}}}Copy the code

Note:

Test match path test match path

. common: { name:'common',
  chunks: 'initial',
  priority: 11,
  enforce: true,
  reuseExistingChunk: true.test: /[\/]node_modules[\/](vue|babel\-polyfill|mint\-ui)/
}
...
Copy the code

The test match is based on the Linux environment path. (such as: node_modules/vue)

But the Window path, unlike the Linux path, is a backslash. (such as: node_modules \ vue)

So we’re going to change the re to

/[\/|\\]node_modules[\/|\\](vue|babel\-polyfill|mint\-ui)/
Copy the code

This allows for compatibility with both environments

Configuration in the project

Webpack typically requires three configuration files

  • Webpack.base.conf.js // Common configuration
  • Webpack.dev.conf.js // Development environment configuration
  • Webpack.prod.conf.js // Production environment configuration

But the configuration you see in our project is not exactly the same as the one described above.

This is because: We already integrated the basic configuration of WebPack when we scaffolded the project.

They’re all under @zz/webpack-vue

Only a few configuration object entries are exposed in our project.

The configuration item structure exposed is slightly different from that of WebPack itself.

Developers can customize these objects, which are then merged with the default configuration to form the final configuration parameters.

(This article is a share of the internal thematic study Webpack, the content is relatively basic)