使用webpack 搭建react项目 二

444 阅读4分钟

本节重点讲解解析器 resolve的配置 和 其他插件 plugins的配置

一、resolve

配置项详解:

  • modules: 告诉webpack 解析模块是应该搜索的目录,即import * from ‘*’ 时应该搜索的目录
  • alias: 项目中 使用import 或者require 时的别名
  • enforceExtension: enforceExtension如果是true,将不允许无扩展名(extension-less)文件,默认如果 ./foo 有 .js 扩展,require('./foo') 可以正常运行。但如果启用此选项,只有require('./foo.js') 能够正常工作
  • extensions: 自动解析确定的扩展, 在引入模块时不带扩展 import File from '../path/to/file',不需要带扩展.js .less 等等
 resolve: {
   modules: [path.resolve(__dirname, 'src'), 'node_modules'],
   alias: {
     '@': path.resolve(__dirname, './src'),
     'api': path.resolve(__dirname, './src/publics/Api'),
     'util': path.resolve(__dirname, './src/publics/common/util'),
     'Comps': path.resolve(__dirname, './src/components'),
     'Form': path.resolve(__dirname, './src/components/Form'),
     'Hoc': path.resolve(__dirname, './src/components/Hoc'),
     'globalRedux': path.resolve(__dirname, './src/redux'),
     'hooks': path.resolve(__dirname, './src/publics/common/hooks'),
   }
   /* resolve.enforceExtension如果是 true,将不允许无扩展名(extension-less)文件。默认如果 ./foo 有 .js 扩展,require('./foo') 可以正常运行。但如果启用此选项,只有 require('./foo.js') 能够正常工作。 */
   enforceExtension: false,
   extensions: ['.js', '.jsx', '.json', '.css', '.less']
 }
}

以上 alias,例如,在page目录下 引入文件的原本路径为: import Input from '../component/Form/Input' 简化路径可以修改为: import Input from ’Form/Input‘

二、一些补充的plugins

一、NamedModulesPlugin

用于启动HMR 热更新时可以显示模块的相对路径,多用于开发环境development

new webpack.NamedModulesPlugin()
new webpack.HotModuleReplacementPlugin()

二、HotModuleReplacementPlugin

模块热更新,即局部更新的插件,多用于开发环境

三、开发环境启动浏览器 使用webpack-dev-server

配置详情:

 devServer: {
    contentBase: '/', //静态文件的文件夹地址,默认为当前文件夹 为根文件夹提供本地服务器,如果想为另外一个目录下的文件提供本地服务器,应该在这里设置其所在目录
    port: 3000, //  监听端口
    historyApiFallback: true,
    //colors: true, //  使用颜色,有利于找出关键信息,只能在控制台中使用
    hot: true, //  启用热替换属性
    // hotOnly: true,  // 开启该属性之后 修改js文件不会刷新页面
    //info: true, //·  在控制台输出信息,默认输出
    open: true, //  运行命令之后自动打开浏览器
    progress: true //将运行进度输出到控制台,只可以使用控制台
  },

上述配置也可以在 package.json里通过script 启动命令时配置:

"start": "cross-env ENV=development webpack-dev-server --open --colors --config webpack.dev.js",

四、优化 optimization 生产环境配置项(压缩,分包等)

首先明确webpack里module。chunk。bundle的意义

1.module:就是js的模块化webpack支持commonJS、ES6等模块化规范,简单来说就是你通过import语句引入的代码。

2.chunk: chunk是webpack根据功能拆分出来的,包含三种情况

3.bundle:bundle是webpack打包之后的各个文件,一般就是和chunk是一对一的关系,bundle就是对chunk进行编译压缩打包等处理之后的产出。 chunk 包含的三种情况:

1)、你的项目入口(entry)

2)、通过import()动态引入的代码

3)、通过splitChunks拆分出来的代码,chunk包含着module,可能是一对多也可能是一对一

webpack的优化配置一般在 optimization 选项里,主要有如下几项:

  • splitChunks webpack分包打包js策略 optimization.splitChunks抽离第三方库,内部其实使用了split-chunks-plugin插件。将业务代码、第三方类库、runtime 代码、css 单独打包,给他们不同 hash,来最大化利用缓存
  • runtimeChunk 是否抽离webpack runtime到单独的文件
  • minimizer 压缩器,webpack4 中使用 terser-webpack-plugin 来替代之前的 uglifyjs-webpack-plugin 压缩器(需要npm 安装),css压缩使用 optimize-css-assets-webpack-plugin
module.exports = {
  //...
  optimization: {
    splitChunks: {
      /*
       *chunks属性用来选择分割哪些代码块,可选值有:'all'(所有代码块),'async'(按需加载的代码块),'initial'(初始化代码块)
       *initial:告诉webpack,将动态导入的文件和非动态导入的文件分别打包,如果一个模块被动态引入,也被非动态引入。那么这个模块将会被分离2次。被分别打包到不同的文件中。
       *  */
      chunks: 'all',
      minSize: 120 * 1024, // 抽离体积大于120kb的chunk
      minChunks: 2, // 抽离被多个入口引用次数大于等于1的chunk
      automaticNameDelimiter: '--', // 分包打包生成文件的名称的连接符
      cacheGroups: { //  cacheGroups 缓存组,如:将某个特定的库打包
        /* 抽离node_modules下的第三方库 可视需要打开会生成两个文件  vender: node-module下的文件*/
        vendor: {
          chunks:'all',
          name:'vender',
          test: (module, chunks) => {
            if (/node_modules/.test(module.context)) {
              return true
            }
          },
          minChunks: 2,//  提取公共部分最少的文件数
          priority: 10,
          enforce: true
        },
        /* 提取共用部分,一下提取的部分会议commons 命名 */
        commons: {
          name: 'commons',
          test: function (module, chunks) {
            if (/src\/components\//.test(module.context) ||
              /src\/common\/util\//.test(module.context) ||
              /react/.test(module.context) ||
              /react-dom/.test(module.context) ||
              /moment/.test(module.context) ||
              /redux/.test(module.context)) {
              return true
            }
          },
          chunks: 'all',
          minChunks: 2, //  提取公共部分最少的文件数
          minSize: 0 // 提取公共部分最小的大小
          // enforce: true
        }
      }
    },
     minimizer: [
      new TerserPlugin({  // 压缩js
        cache: true,
        parallel: true,
        terserOptions: {
          compress: {
            drop_console: true,
            drop_debugger: true // 去除console.log 和debuger
          },

      }),
      new OptimizeCSSAssetsPlugin({})  // 压缩css
    ]
    
  }
};