重学webpack(配置详解)

757 阅读13分钟

webpack的四篇学习笔记

配置详解

  • entry的不同配置写法
  • ouput的不同配置写法
  • module的不同配置的写法
  • resolve的不同配置的写法
  • devServer的不同配置的写法
  • optimization的不同配置的写法

entry的不同配置写法

  • 第一种写法:字符串写法(单入口)即entry:'./src/index.js'的配置写法,构建目录和具体的配置代码如下:
  • optimization的不同配置的写法
//下面是webpack.config.js的代码

const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');



module.exports = {
    //单入口
  entry:'./src/index.js',
  output: {
    filename: 'built.js',
    path: resolve(__dirname, 'build')
  },
  plugins: [
// 功能:默认会创建一个空的HTML,自动引入打包输出的所有资源(JS/CSS)
// 这里是执行webpack指令后自动将build/built.js引入
// 这里不需要创建有结构的HTML文件
// 所以不需要添加额外的配置
  	new HtmlWebpackPlugin()
  ],
  mode: 'development'
};

----------------------------------------------

//下面是src/index.js文件的代码(单入口)
// 单入口时由src/index.js文件引入这两个文件

import add from './add';
import count from './count';

console.log('index.js文件加载了~');
console.log(add(1, 2));
console.log(count(3, 2));

----------------------------------------------


//下面是src/add.js文件的代码
function add(x, y) {
  return x + y;
}

export default add;

----------------------------------------------


//下面是src/count.js文件的代码
function count(x, y) {
  return x - y;
}

export default count;
  • 第一种写法:执行webpack指令之后,我们会发现webpack自动构建输出了一个JS文件(即build/built.js文件),又因为我们使用了插件new HtmlWebpackPlugin(),这个插件会自动帮我们生成了build/index.html并自动帮我们引入了打包输出的所有资源(这里指的是build/built.js)。
  • 第一种写法的总结:单入口写法即(entry:'./src/index.js'),打包形成一个chunk,输出一个bundle文件,此时chunk的名称默认是 main 。(在上面的webpack.config.js配置中我们指定了输出的文件名称)
  • 第一种写法的注意点:如果我们使用output:{filename: '[name].js',path:resolve(__dirname, 'build')},的配置写法,则输出的该JS文件的名称是默认的名称(即build/main.js),验证了chunk的名称默认是 main。代码如下:
//下面是webpack.config.js的代码


const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry:'./src/index.js',
  output: {
    filename: '[name].js',
    path: resolve(__dirname, 'build')
  },
  plugins: [new HtmlWebpackPlugin()],
  mode: 'development'
};

  • 第二种写法:数组写法(多入口)。即entry:['./src/index.js', './src/count.js']的配置写法。数组写法的特点所有写在数组中的入口文件最终只会形成一个chunk, 输出出去依旧是只有一个bundle文件
  • 第二种写法的注意点:数组写法里的各个文件,打包构建后所有下标大于0的文件资源都会被一起打包整合进下标为0的文件中,如下图所示(默认输出的chunk names叫做main):
  • 第二种写法的注意点:回顾之前的使用HMR优化打包构建速度的代码中,我们因为使用HMR功能导致了源目录下的src/index.html文件不仅使用不了HMR,而且还丧失了WDS的功能。由于HTML页面本身不需要做HMR功能,所以我们只要让其恢复WDS的功能即可,我们的解决方式如下:
  • 第二种写法的注意点:数组写法通常都是用于解决HTML页面因为引入HMR功能后WDS功能失效的问题
//修改了webpack.config.js的配置需要重启服务
//即重新执行npx webpack-dev-server

 entry: ['./src/js/index.js', './src/index.html']
  • 第三种写法:对象写法(多入口)。对象写法的key对应着名称,value对应着文件路径。此时有几个入口文件就形成几个chunk,输出几个bundle文件。注意:chunk names的名称是 key。
  • 我们先来看第三种写法下的第一种情况,代码如下:
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');


module.exports = {
  entry: {
    index: './src/index.js',
    //index.js文件中无需在引入add.js
    //add.js文件也会被单独打包输出为一个文件被自动引入
    add: './src/add.js'
  },
  output: {
    // filename: 'built.js',
    filename: '[name].js',
    path: resolve(__dirname, 'build')
  },
  plugins: [new HtmlWebpackPlugin()],
  mode: 'development'
};

  • 我们再来看第三种写法下的第二种情况,代码如下:
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');



module.exports = {
  entry: {
   //index.js无需在引入count.js和add.js
    index: ['./src/index.js', './src/count.js'], 
    add: './src/add.js'
  },
  output: {
    // filename: 'built.js',
    filename: '[name].js',
    path: resolve(__dirname, 'build')
  },
  plugins: [new HtmlWebpackPlugin()],
  mode: 'development'
};

  • 第三种写法注意点:entry对象写法下index: ['./src/index.js', './src/count.js']所有入口文件最终只会形成一个chunk, 输出出去只有一个bundle文件。
  • 第三种写法注意点:entry对象写法下add: './src/add.js'形成一个chunk,输出一个bundle文件。
  • 第三种写法的启迪:在使用dll来优化打包构建速度中我们配置webpack.dll.js文件时,可以采用entry对象写法下的对象写法,具体代码如下:
//这里是webpack.dll.js的代码:



const { resolve } = require('path');


//使用webpack自带的插件:new webpack.DllPlugin
const webpack = require('webpack');


module.exports = {
  entry: {
    // ['jquery'] --> 要打包的库是jquery
    jquery: ['jquery'],
    react:['react','react-dom','react-router-dom']
  },
  output: {
    // 最终打包生成的文件的[name] ---这里是---> jquery
    filename: '[name].js',  //指定输出的文件名
    path: resolve(__dirname, 'dll'), //指定输出的目录
    library: '[name]_[hash]' // 打包的库(里面)向外暴露出去的内容叫什么名字
  },
  plugins: [
    // 打包生成一个 manifest.json --> 提供和jquery映射(因为这里只打包了jquery)
    new webpack.DllPlugin({
      name: '[name]_[hash]', // 映射库的暴露的内容名称
      path: resolve(__dirname, 'dll/manifest.json') // 输出文件路径
    })
  ],
  mode: 'production'
};
  • entry的不同配置写法的总结:

ouput的不同配置写法

  • 场景:我们接下来在单入口(即entry: './src/index.js')的场景下来研究ouput的不同配置写法。我们可以先回顾一下我们之前写过的ouput的配置写法,代码如下:
//下面是webpack.config.js的代码
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    // 文件名称(指定目录+指定名称)
    // [name]是chunk names的名称
    filename: 'js/[name].js',
    // 指定输出文件目录(将来所有资源输出的公共目录)
    path: resolve(__dirname, 'build'),
  },
  plugins: [new HtmlWebpackPlugin()],
  mode: 'development'
};
  • ouput的配置之publicPath:一般适用于生产环境,可以指定所有资源引入的公共路径的前缀。例如当我配置publicPath: '/'后,我原先的路径 'imgs/a.jpg'经过它的处理会变成'/imgs/a.jpg',路径的转变会导致服务器在请求文件时找的地址发生对应的改变。(决定的是资源引入的路径而不是输出的路径)
  • ouput的配置之chunkFilename:指定非入口chunk的名称,在这里我们配置了entry: './src/index.js',,所以src/index.js文件就是入口chunk(多入口时也就是多入口chunk),其他就是非入口chunk。
  • ouput的配置之chunkFilename的注意点:什么chunk的名称命名会遵循chunkFilename的配置呢?
  • 一个是通过import语法将文件单独分割为一个chunk时该chunk的命名会走chunkFilename的配置。
  • 一个是通过optimization: {splitChunks: {chunks: 'all'}},依赖于node_modules中的第三方库的代码单独打包一个chunk最终输出(单独生成一个文件)的时候会走chunkFilename的配置。
  • 如果不配置chunkFilename则输出的文件名都是走filename配置
  • 构造目录和代码如下:
//下面是webpack.config.js的代码

const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    // 文件名称(指定名称+目录)
    filename: 'js/[name].js',
    // 输出文件目录(将来所有资源输出的公共目录)
    path: resolve(__dirname, 'build'),
    // 指定所有资源引入公共路径前缀
    publicPath: '/',
    // 指定非入口chunk的名称
    // 如果不配置chunkFilename则输出的文件名都是走filename配置
    chunkFilename: 'js/[name]_chunk.js', 
  },
  plugins: [new HtmlWebpackPlugin()],
  mode: 'development'
};

----------------------------------------------


//下面是src/index.js的代码
//使用import语法来演示在这种情况下会走chunkFilename配置

import count from './count';

console.log('index.js文件加载了~');

import('./add').then(({ default: add }) => {
  console.log(add(1, 2));
});

console.log(count(3, 2));




----------------------------------------------


//下面是src/add.js的代码
function add(x, y) {
  return x + y;
}

export default add;


----------------------------------------------

//下面是src/count.js的代码

function count(x, y) {
  return x - y;
}

export default count;

  • ouput的配置之library和libraryTarget:它们的作用分别是指定整个库向外暴露的变量名和变量名添加到哪个上(window\global\commonjs)

  • ouput的配置总结写法:
//下面是webpack.config.js的代码


const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    // 文件名称(指定名称+目录)
    filename: 'js/[name].js',
    // 输出文件目录(将来所有资源输出的公共目录)
    path: resolve(__dirname, 'build'),
    // 所有资源引入公共路径前缀 --> 'imgs/a.jpg' --> '/imgs/a.jpg'
    publicPath: '/',
    chunkFilename: 'js/[name]_chunk.js', // 非入口chunk的名称
    // library: '[name]', // 整个库向外暴露的变量名
    // libraryTarget: 'window' // 变量名添加到哪个上 browser
    // libraryTarget: 'global' // 变量名添加到哪个上 node
    // libraryTarget: 'commonjs'
  },
  plugins: [new HtmlWebpackPlugin()],
  mode: 'development'
};
  • ouput的不同配置写法的总结:

module的不同配置的写法

  • 使用多个loader配置时的写法:
{
  test: /\.css$/,
  // 多个loader用use
  use: ['style-loader', 'css-loader']
},
  • 使用单个loader配置时的写法:
{
  test: /\.js$/,
  loader: 'eslint-loader'
},
  • 使用loader配置时额外添加其他配置选项的写法:
{
  test: /\.js$/,
  // 排除node_modules下的js文件
  exclude: /node_modules/,
  // 只检查 src 下的js文件
  include: resolve(__dirname, 'src'),
  // 优先执行
  enforce: 'pre',
  // 延后执行
  // enforce: 'post',
  
  
  loader: 'eslint-loader',
  
  
  
  options: {}
},
  • 使用loader配置时配合oneOf规则使用的写法:
{
    // 以下loader匹配命中一个文件后后续的loader不会在对这个文件进行检查
    // 注意:不能有两个配置处理同一种类型文件
    oneOf: [
      {
        test: /\.(jpg|png|gif)/,
        loader: 'url-loader',
        options: {
          limit: 8 * 1024,
          name: '[hash:10].[ext]',
          outputPath: 'imgs',
          esModule: false
        }
      },
      {
        test: /\.html$/,
        loader: 'html-loader'
      },
      {
        exclude: /\.(js|css|less|html|jpg|png|gif)/,
        loader: 'file-loader',
        options: {
          outputPath: 'media'
        }
      }
    ]
},
  • loader配置的不同写法的总结:
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'js/[name].js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      // loader的配置
      {
        test: /\.css$/,
        // 多个loader用use
        use: ['style-loader', 'css-loader']
      },
      {
        test: /\.js$/,
        // 排除node_modules下的js文件
        exclude: /node_modules/,
        // 只检查 src 下的js文件
        include: resolve(__dirname, 'src'),
        // 优先执行
        enforce: 'pre',
        // 延后执行
        // enforce: 'post',
        // 单个loader用loader
        loader: 'eslint-loader',
        options: {}
      },
      {
        // 以下配置只会生效一个
        oneOf: []
      }
    ]
  },
  plugins: [new HtmlWebpackPlugin()],
  mode: 'development'
};

resolve的不同配置的写法

  • 场景回顾:我们在入口文件中(这里是src/js/index.js文件)去引入样式文件(这里是src/css/index.css文件),正常来说,我们的代码如下:
//下面是src/js/index.js的代码:

//第一种引入index.css的方式
//注意路径:
import '../css/index.css'
  • 场景回顾:如果我们的项目十分的庞大,需要引用的文件的路径十分的深层,上面的写法是比较繁琐的。我们可以在webpack.config.js中去使用resolve,来定义解析模块的规则。
  • 下面是使用resolve配置的webpack.config.js的代码:
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/[name].js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      }
    ]
  },
  plugins: [new HtmlWebpackPlugin()],
  mode: 'development',
  // 解析模块的规则
  resolve: {
    // 配置解析模块路径别名
    // 优点简写路径 缺点路径没有提示
    alias: {
      $css: resolve(__dirname, 'src/css')
    },
    // 配置省略文件路径的后缀名
    // 注意:配置extensions后目录下的文件名千万不要取一样的
    extensions: ['.js', '.json', '.jsx', '.css'],
    // 告诉 webpack 去哪个目录下找到node_modules
    // 准确找到node_modules所在
    // 不用在一级一级的向上去查找node_modules
    modules: [resolve(__dirname, '../../node_modules'), 'node_modules']
  }
};
  • webpack.config.js中配置resolve后我们再来看我们的入口文件(src/js/index.js)引入样式文件(src/css/index.css)的路径写法:
//下面是src/js/index.js的代码:


//第二种引入index.css的方式
//第二种方式使用了resolve配置规则
//即resolve: {alias: {$css: resolve(__dirname, 'src/css')},}
//优点是简写路径 缺点是路径没有提示
//import '$css/index.css'

-------------------------------------------------


//第三种引入index.css的方式
//在第二种配置的基础上增加配置省略文件路径的后缀名
//配置extensions后目录下的文件名千万不要取一样的


import '$css/index';
  • resolve的不同配置的写法的总结:

devServer的不同配置的写法

  • 场景回顾:我们先来回顾一下之前在开发环境下对devServer的做过的配置,代码如下:
devServer: {
    //运行代码的目录、项目构建后的路径
    //托管服务器的目录通常指定为通过webpack构建后的目录
    //即一般与在ouput中配置的path: resolve(__dirname, 'build')一致
    contentBase: resolve(__dirname, 'build'),
    //启用gzip压缩
    compress:true,
    //端口号
    port:3000,
    //自动打开浏览器
    open:true
  }
  • 接着我们来看更多的关于devServer的不同配置的写法,代码如下:
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/[name].js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      }
    ]
  },
  plugins: [new HtmlWebpackPlugin()],
  mode: 'development',
  devServer: {
  
  
    // 运行代码的目录
    //一般与在ouput中配置的path: resolve(__dirname, 'build')一致
    contentBase: resolve(__dirname, 'build'),
    
    
    // 监视 contentBase 目录下的所有文件,一旦文件变化就会 reload
    watchContentBase: true,
    
    
    watchOptions: {
      // 监视时需要忽略某些文件
      ignored: /node_modules/
    },
    
    
    // 启动gzip压缩
    compress: true,
    
    
    // 端口号
    port: 5000,
    
    
    // 域名
    host: 'localhost',
    
    
    // 自动打开浏览器
    open: true,
    
    
    // 开启HMR功能
    hot: true,
    
    
    // 不要显示启动服务器日志信息
    clientLogLevel: 'none',
    
    
    // 除了一些基本启动信息以外,其他内容都不要显示
    quiet: true,
    
    
    // 如果出错了,不要全屏提示~
    overlay: false,
    
    
    // 服务器代理 --> 解决开发环境跨域问题
    proxy: {
      // 一旦devServer(5000)服务器接受到 /api/xxx 的请求,
      // 就会把请求转发到另外一个服务器(3000)
      '/api': {
        target: 'http://localhost:3000',
        // 发送请求时,请求路径重写:
        // 将 /api/xxx --重写为--> /xxx (去掉/api)
        pathRewrite: {
          '^/api': ''
        }
      }
    }
  }
};
  • devServer的配置中proxy(服务器代理)和hot(开启HMR功能)和port(端口号)和host(域名)和contentBase(托管服务器的目录)这几个选项是经常需要用到的。

optimization的不同配置的写法

  • 场景回顾:我们之前在生产环境下使用code split来优化代码运行的性能使用过optimization的配置,代码如下:
//webpack.config.js的代码


/*
1. 单入口时可以将依赖于node_modules中的第三方库的代码
  单独打包一个chunk最终输出(单独生成一个文件)
  
2. 多入口时(上面的事情也会做)还可以自动分析
   多入口的chunk中有没有公共依赖的文件。
   如果有会打包成单独一个chunk(输出时单独生成一个文件)
*/


optimization: {
  splitChunks: {
    chunks: 'all'
  }
},
  • 接着我们来研究下optimization配置里面的其他选项配置信息。我们先来看optimization配置下splitChunks里面的其他可选配置信息,代码如下:
optimization: {
  splitChunks: {
    chunks: 'all',




    
/*  // 下面都是默认值可以不写
    // 只有在你打算修改默认值时才需要写


    // 分割的chunk最小为30kb
    minSize: 30 * 1024, 
    
    // 最大没有限制
    maxSiza: 0, 
    
    // 要提取的chunk最少被引用1次
    minChunks: 1, 
    
    // 按需加载时并行加载的文件的最大数量
    maxAsyncRequests: 5, 
    
    // 入口js文件最大并行请求数量
    maxInitialRequests: 3, 
    
    // 名称连接符
    automaticNameDelimiter: '~', 
    
    // 可以使用命名规则
    name: true, 
    
    
    cacheGroups: {
      // 分割chunk的组
      // node_modules文件会被打包到 vendors 组的chunk中。
      // --> vendors~xxx.js
      // 满足上面的公共规则,
      // 如:大小超过30kb,至少被引用一次。
      vendors: {
        test: /[\\/]node_modules[\\/]/,
        // 优先级
        priority: -10
      },
      default: {
        // 要提取的chunk最少被引用2次
        minChunks: 2,
        // 优先级
        priority: -20,
        // 如果当前要打包的模块,
        // 和之前已经被提取的模块是同一个
        // 就会复用,而不是重新打包模块
        reuseExistingChunk: true
      } 
    }
    
    
*/
  },
}
  • 我们在通过一个场景来看下optimization配置下runtimeChunk里面的其他可选配置信息的作用:场景是我们在src/js/index.js文件中通过import的方式去引入src/js/a.js文件,代码如下:
//下面是src/js/index.js的代码:


//执行webpack指令后构建后的
//文件名为a.[contenthash:10]_chunk.js

import(/* webpackChunkName: 'a' */'./a.js').then(({ add }) => {
  console.log(add(1, 2));
});


---------------------------------------------------


//下面是src/js/a.js的代码:
export function add(x, y) {
  return x + y;
}

---------------------------------------------------

//下面是webpack.config.js的代码:


const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const TerserWebpackPlugin = require('terser-webpack-plugin')

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/[name].[contenthash:10].js',
    path: resolve(__dirname, 'build'),
    chunkFilename: 'js/[name].[contenthash:10]_chunk.js'
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      }
    ]
  },
  plugins: [new HtmlWebpackPlugin()],
  mode: 'production',
  optimization: {
    splitChunks: {
      chunks: 'all'
    }
  }
};

  • 在上述的场景中,我们在我们在output里配置了chunkFilename: 'js/[name].[contenthash:10]_chunk.js'。因为通过import语法将文件单独分割为一个chunk时该chunk的命名会走chunkFilename的配置。执行webpack指令后,该构建后的目录结构是:
  • 我们可以在该场景中分析得到:因为src/js/index.js引入了a.js,所以a.js文件依赖于index.js文件,执行wepack之后打包构建后的js/main.[contenthash:10].js文件记录着js/a.[contenthash:10].js文件的contenthash值,在只修改js/a.[contenthash:10].js文件的情况下,会导致js/main.[contenthash:10].js文件也跟着改变。这种问题我们是可以解决的。
  • 该场景的解决思路:我们可以将打包构建后的js/main.[contenthash:10].js文件记录着的js/a.[contenthash:10].js文件中的contenthash值给单独提取出来。这样子js/main.[contenthash:10].js文件就不去记录js/a.[contenthash:10].js文件的contenthash值。现在js/a.[contenthash:10].js文件的内容改变后就不会影响到js/main.[contenthash:10].js文件了
  • 该场景的解决实现:使用optimization配置下的runtimeChunk,代码如下:
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const TerserWebpackPlugin = require('terser-webpack-plugin')

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/[name].[contenthash:10].js',
    path: resolve(__dirname, 'build'),
    chunkFilename: 'js/[name].[contenthash:10]_chunk.js'
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      }
    ]
  },
  plugins: [new HtmlWebpackPlugin()],
  mode: 'production',
  optimization: {
    splitChunks: {
      chunks: 'all'
    },
    // 将当前模块的记录其他模块的hash值
    // (这里是记录contenthash)
    // 单独打包为一个文件 runtime
    // 解决问题:修改a文件导致b文件的contenthash变化,从而导致缓存失效
    runtimeChunk: {
      name: entrypoint => `runtime-${entrypoint.name}`
    }
  }
};

  • 场景总结:当js/a.[contenthash:10].js文件改变时,我们重新执行webpack指令后,只有js/a.[contenthash:10].js文件runtime文件发生改变了,js/main.[contenthash:10].js文件是不会改变的。
  • 我们最后在看下optimization配置下的minimizer配置(这里用到了'terser-webpack-plugin'即需要cnpm i 'terser-webpack-plugin' -D)。代码如下:(生产环境)
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const TerserWebpackPlugin = require('terser-webpack-plugin')

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/[name].[contenthash:10].js',
    path: resolve(__dirname, 'build'),
    chunkFilename: 'js/[name].[contenthash:10]_chunk.js'
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      }
    ]
  },
  plugins: [new HtmlWebpackPlugin()],
  mode: 'production',
  optimization: {
    splitChunks: {
      chunks: 'all'
    },
    runtimeChunk: {
      name: entrypoint => `runtime-${entrypoint.name}`
    },
    minimizer: [
      // 配置生产环境的压缩方案:js和css
      new TerserWebpackPlugin({
        // 开启缓存
        cache: true,
        // 开启多进程打包
        parallel: true,
        // 启动source-map
        sourceMap: true
      })
    ]
  }
};

  • 现在生产环境的压缩方案:压缩js和css请使用'terser-webpack-plugin',尽量不要在使用UglifyJsPlugin了。
  • optimization的不同配置的写法的总结:
  • 该项目的package.json文件的代码内容为:
{
  "name": "webpack_code",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.8.4",
    "@babel/polyfill": "^7.8.3",
    "@babel/preset-env": "^7.8.4",
    "add-asset-html-webpack-plugin": "^3.1.3",
    "babel": "^6.23.0",
    "babel-loader": "^8.0.6",
    "core-js": "^3.6.4",
    "css-loader": "^3.4.2",
    "eslint": "^6.8.0",
    "eslint-config-airbnb-base": "^14.0.0",
    "eslint-loader": "^3.0.3",
    "eslint-plugin-import": "^2.20.1",
    "file-loader": "^5.0.2",
    "html-loader": "^0.5.5",
    "html-webpack-plugin": "^3.2.0",
    "less": "^3.11.1",
    "less-loader": "^5.0.0",
    "mini-css-extract-plugin": "^0.9.0",
    "optimize-css-assets-webpack-plugin": "^5.0.3",
    "postcss-loader": "^3.0.0",
    "postcss-preset-env": "^6.7.0",
    "style-loader": "^1.1.3",
    "terser-webpack-plugin": "^2.3.5",
    "thread-loader": "^2.1.3",
    "url-loader": "^3.0.0",
    "webpack": "^4.41.6",
    "webpack-cli": "^3.3.11",
    "webpack-dev-server": "^3.10.3",
    "workbox-webpack-plugin": "^5.0.0"
  },
  "dependencies": {
    "jquery": "^3.4.1"
  },
  "browserslist": {
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ],
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ]
  },
  "eslintConfig": {
    "extends": "airbnb-base",
    "env": {
      "browser": true
    }
  },
  "sideEffects": [
    "*.css"
  ]
}