最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • Webpack从手把手配置到原理浅析(二):高级配置

    正文概述 掘金(ScarlettLL)   2020-12-27   516

    上一篇文章介绍了最基本的Webpack配置,可以满足一个前端项目最基本的构建和打包需求。 本文在基本配置上,增加更高级的配置,包括多入口处理、压缩CSS、公共代码和第三方库打包优化和懒加载。

    多入口处理

    上一节介绍的配置都是单一入口文件,最终打包产出单一HTML文件。 如果想要最终产出多个HTML文件,那么就需要配置多入口。

    1. 配置多个entry

    之前在基本配置里,入口配置是放在webpack.base.conf.js下:

    entry: path.join(srcPath, 'index')
    

    这里的意思是把src/index.js作为打包构建的唯一入口文件。 如果要配置多入口,此时的entry不再是一个字符串,而是一个对象,每一对键值对就是一个入口,其中的key是每个入口文件形成chunk后的唯一标识,下面配置pluginsoutput时会利用到这些标识:

    entry: {
      index: path.join(srcPath, 'index.js'),
      other: path.join(srcPath, 'other.js')
    }
    

    2. 配置HtmlWebpackPlugin

    上一节说到,HtmlWebpackPlugin是用来生成最终的HTML文件,所有打包后的bundle文件都会以script标签的形式存在于这个HTML文件内加载出来。 一个HtmlWebpackPlugin配置就会生成一个HTML文件,所以想要最终有多个HTML文件,就需要配置多个HtmlWebpackPlugin

    • template:模板html文件
    • filename:打包后的文件名
    • chunks:当前页面需要引用的chunks标识,默认全部引用
    plugins: [
      // 多入口 - 生成 index.html
      new HtmlWebpackPlugin({
          template: path.join(srcPath, 'index.html'),
          filename: 'index.html',
          // chunks 表示该页面要引用哪些 chunk (即上面的 index 和 other),默认全部引用
          chunks: ['index']  // 只引用 index.js
      }),
      // 多入口 - 生成 other.html
      new HtmlWebpackPlugin({
          template: path.join(srcPath, 'other.html'),
          filename: 'other.html',
          chunks: ['other']  // 只引用 other.js
      })
    ]
    

    3. 配置输出output

    上一节的基本配置我们是这么配置output的:

    output: {
      filename: 'bundle.[contentHash:8].js',  // 打包代码时,加上 hash 戳
      path: distPath,
     },
    

    这样的配置会导致最终所有打包后的bundle文件都叫bundle.xxx.js文件,不好区分是哪个入口。 所以输出配置这里要利用入口文件的chunk标识,对输出的bundle文件进行命名:

    output: {
      filename: '[name].[contentHash:8].js', // name 即多入口时 entry 的 key
      path: distPath,
    },
    

    压缩CSS

    在上一节基础配置里,我们是通过css-loaderstyle-loader等将CSS文件最终处理为style样式,最终以style的方式注入到最终打包形成的JS文件。 但是这样的做法会导致最终打包出来的JS文件比较大,初次加载的时间比较长。 所以对于CSS文件,考虑有两点优化的地方:

    • 要从JS文件中抽离出来,JS文件和样式文件分别引入,加快加载速度
    • 对CSS代码进行产出优化,对它们进行压缩,减小打包后的体积

    1. 使用mini-css-extract-plugin.loader解析,抽离CSS文件

    我们可以使用mini-css-extract-plugin实现抽离CSS目标,只要将之前使用style-loader,改为使用MiniCssExtractPlugin.loader即可。

    使用mini-css-extract-plugin好处:

    • CSS不再通过style的方式引入,打包过后的js文件也不会有css相关的内容
    • 所有的CSS都通过link标签加载,速度更快
    const MiniCssExtractPlugin = require('mini-css-extract-plugin');
    
    // ...
    module: {
      rules: [
        // 抽离 css
        {
          test: /\.css$/,
          loader: [
              MiniCssExtractPlugin.loader,
              'css-loader',
              'postcss-loader'
          ]
        },
        // 抽离 less --> css
        {
          test: /\.less$/,
          loader: [
              MiniCssExtractPlugin.loader,
              'css-loader',
              'less-loader',
              'postcss-loader'
          ]
        }
      ]
    },
    

    2. 利用缓存的CSS文件

    利用hash给打包后的CSS文件进行命名,利用浏览器缓存策略,命中名字的CSS文件不会重新加载,加快加载速度。

    plugins: [
      new CleanWebpackPlugin(), // 会默认清空 output.path 文件夹
      new webpack.DefinePlugin({
          // window.ENV = 'production'
          ENV: JSON.stringify('production')
      }),
    
      // 设置打包后的CSS文件名,利用缓存
      new MiniCssExtractPlugin({
          filename: 'css/main.[contentHash:8].css'
      })
    ],
    

    3.optimize-css-assets-webpack-plugin对CSS压缩

    optimize-css-assets-webpack-plugin主要的压缩策略是删除CSS文件里的空格和注释。

    optimization: {
      minimizer: [
        new TerserJSPlugin({}),// 压缩JS
        new OptimizeCSSAssetsPlugin({})// 压缩 css
      ],
    }
    

    抽离公共代码和第三方代码

    我们在开发中,经常会抽取复用的公共代码,以及第三方库,通过import的方式引入,减少重复代码,提升开发效率。 但是在打包过程中,Webpack会解析文件的引入,会把引入的文件也打包,这样就造成了公共的代码的重复打包,给打包后的文件增加了不必要的体积。 所以对于公共代码,我们可以考虑将其分割抽离出来,形成一个个个单独的chunk,然后在入口配置时决定每个入口使用哪些chunk,这样可以减少重复打包,实现按需加载。

    1. 分割代码块

    通过在optimization设置splitChunks去分割代码块,可以将第三方库代码和公共代码分别分割成一个chunk。 配置要点:

    • cacheGroups里去定义分割标准,其中的key就是这个chunk的名字
    • test字段配置chunk的文件范围
    • minSize字段决定体积规则,minChunks字段决定复用次数规则,即只有超过minSize的体积和复用超过minChunks次才的代码,才会被抽离成相应的chunk
    • priority字段决定当前抽离规则的优先级,数值越大,优先级越高
    optimization: {
      // 分割代码块
      splitChunks: {
        chunks: 'all',
        // 缓存分组
        cacheGroups: {
          // 第三方模块
          vendor: {
            name: 'vendor', // chunk 名称
            priority: 1, // 权限更高,优先抽离
            test: /node_modules/,
            minSize: 0,  // 大小限制
            minChunks: 1  // 最少复用过几次
          },
    
          // 公共的模块
          common: {
            name: 'common', // chunk 名称
            priority: 0, // 优先级
            minSize: 0,  // 公共模块的大小限制
            minChunks: 2  // 公共模块最少复用过几次
          }
        }
      }
    }
    

    2. 配置入口

    在设置完代码分割规则后,需要在入口配置,决定每个入口分别使用哪些chunk,实现按需加载。

     plugins: [
      // 多入口 - 生成 index.html
      new HtmlWebpackPlugin({
        template: path.join(srcPath, 'index.html'),
        filename: 'index.html',
        // chunks 表示该页面要引用哪些 chunk,默认全部引用
        chunks: ['index', 'vendor', 'common']  // 要考虑代码分割
      }),
      // 多入口 - 生成 other.html
      new HtmlWebpackPlugin({
        template: path.join(srcPath, 'other.html'),
        filename: 'other.html',
        chunks: ['other', 'common']  // 考虑代码分割
      })
    ]
    

    上面配置的chunks数组中, vendorcommon是我们在optimization.splitChunks分割的chunk,那么剩下的indexother是哪儿来的? 别忘了,我们在多入口配置里讲过,配置入口entry也会形成chunk,所以这里的indexother,就是在配置多入口时的两个chunk

    总结一下会形成chunk的地方:

    • entry
    • optimization.splitChunks

    懒加载

    通过使用webpack的'dynamic import', 可以将打包的代码分割成不同的chunk,加快首次加载的速度。 React和Vue都提供了异步加载组件的方式,异步加载的组件不会阻塞主页面的渲染,首屏加载速度更快,所以我们可以考虑将一些次要的、较为复杂的组件通过异步的方式引入,实现'dynamic import'。

    React懒加载

    React可以使用React.lazy()实现懒加载:

    const Chart = React.lazy(() => {
      import("./Chart");// Webpack打包之后的chunk名字就是Chart
    })
    

    Vue懒加载

    Vue实现懒加载有两种方式:一是异步组件声明,二是通过路由懒加载。

    异步组件声明

    Vue.component('chart', () => import('./chart'));
    

    路由懒加载

    const chart = () => import('./chart');
    
    // 路由引入
    const routes = [
      {
       name: "Chart",
       path: 'chart',
       component: chart
      }
    ]
    

    起源地下载网 » Webpack从手把手配置到原理浅析(二):高级配置

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元