webpack 常用配置解析(三)

1、懒加载与预加载
index.js

console.log('index');

document.querySelector('#btn').onclick=function(){
  // 懒加载
  import(/* webpackChunkName:'test' */'./test').then(({test1})=>{
    console.log('test1test1', test1(6));
  })
}

test.js

console.log('test');
export const test1 = (a)=>{
  console.log('a11',a);
  return a +3
}

这个时候,我点击页面的btn按钮时才会加载test.js文件

预加载

document.querySelector('#btn').onclick=function(){
  // 懒加载  import语法  文件需要用的时候才加载 (会有延迟效果)
  // 预加载 webpackPrefetch: true  会在使用之前提前加载js文件
// 正常加载是并行加载(同一时间加载多个文件)
// 预加载Prefetch等其他文件加载完毕,浏览器空闲了,再加载资源
  import(/* webpackChunkName:'test2', webpackPrefetch:true */'./test').then(({test1})=>{
    console.log('test1test1', test1(6));
  })
}

2、PWA (在服务器中才行)
https://www.jianshu.com/p/74db1b1f90a7
https://www.jianshu.com/p/f28341217c4f

/**
 * PWA 渐进式网络开发应用程序
 * workbox --->workbox-webpack-plugin
 * **/
const WorkboxWebpackPlugin = require('workbox-webpack-plugin')
...
plugins: [
new WorkboxWebpackPlugin.GenerateSW({
  // 帮助serviceworker快速启动
      // 删除就的serviceworker
      clientsClaim: true,
      skipWaiting: true
    })

index.js

// serviceWorker
if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
      navigator.serviceWorker.register('/service-worker.js').then(registration => {
      console.log('SW registered: ', registration);
      }).catch(registrationError => {
      console.log('SW registration failed: ', registrationError);
      });
  });
}

3、多进程打包,优化打包速度
项目变的庞大,文件很多的情况下,采取多进程打包

            test: /\.js$/,
            exclude: /node_modules/,
            use: [
              /**
               * 开启多进程打包 
               * 进程开启大概600ms,进程通信也有开销
               * 只有工作消耗时间比较长的时候,才需要多进程打包
               * 如果小项目,文件不多,无需开启多进程打包,反而会变慢,因为开启进程是需要花费时间的
               * */ 
               {
                loader: 'thread-loader',
                options: {
                  workers: 2 // 进程2个
                }
              },
              {
                loader: 'babel-loader',
                options: {
....

4、externals 不把某些文件打包
之后我们要在html中手动引入,一般使用cdn,这样可能比我们访问我们的资源要快一些。

  externals: {
    // 忽略库名---》npm 包名
    jquery: 'jQuery'
  }

5、_dll
为了把node_modules里面的代码打包成不同chunk.
上面externals是不打包jquery,通过cdn引入。下面是单独把jquery 打包出去,并引入文件 ,
需要新建一个文件
webpack.dll.js

/**
 * 使用dll技术,对某些库(第三方库比如: jquery, react, vue,...)进行单独打包
 * 运行webpack时,默认查找webpack.config.js配置文件
 * 所以我们运行时,需要webpack --config webpack.dll.js
 * 
*/
const path = require('path')
const webpack = require('webpack')
module.exports={
  entry:{
    // 最终打包生成的[name] 
    // ['jquery'] 要打包的库
    jquery: ['jquery',]
  },
  output: {
    filename: '[name].js',
    path: path.resolve(__dirname, 'dll'),
    library: '[name]_[hash]', //打包库里面暴露出去的内容叫什么

  },
  plugins:[
    // 打包生成一个json文件 ,提供映射关系
    new webpack.DllPlugin({
      name: '[name]_[hash]', // 映射库暴露的内容名称
      path: path.resolve(__dirname, 'dll/manifest.json') // 输出的文件路径
    })
  ]
}

然后修改 webpack.config.js

const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin')
const webpack = require('webpack')
...

plugins:[
// 告诉webpack哪些库不参与打包,同时使用是名称也要变
    new webpack.DllReferencePlugin({
      manifest: path.resolve(__dirname, 'dll/manifest.json')
    }),
    // 将某个文件打包输出去,并在HTML中自动引入该资源
    new AddAssetHtmlWebpackPlugin({
      filepath: path.resolve(__dirname, 'dll/jquery.js')
    })

entry

/**
   * entry : 入口
   * 1、string ---> './src/index.js
   *  单入口
   *  打包形成一个chunk.输出一个bundle文件
   *  此时chunk的名称默认是main
   * 2、array ----> ['./src/index.js', './src/test.js']
   *  多入口
   *  所有入口文件最终会形成一个chunk,输出文件只有一个bundle文件
   *  ---》 只有HMR功能中能让html热更新生效
   * 3、object
   *  多入口
   *  有几个入口文件就形成几个chunk,输出一个bundle文件
   *  初始chunk的名称是key
  */
  //入口
  entry: {
    index: './src/index.js'
  },

output

output: {
    // 文件名称(指定名称 + 目录)
    filename: 'js/[name].[contenthash:5].js',
    // 输出文件目录
    path: path.resolve(__dirname, 'build'),
    // 素有资源引入公共路径前缀
    publicPath: '/',
    // 非入口chunk的名称
    chunkFilename: 'js/[name]_chunk.js',
    library: '[name]', // 整个库向外暴露的变量名, 结合dll使用
    // libraryTarget: 'window', // 变量名添加到 window上
    // libraryTarget: 'gloabal', // 变量名添加到 gloabal
    libraryTarget: 'commonjs', // 用模块化引用
  },

loader

// loader
  module: {
    rules: [
      {
        test: /\.js$/,
        // 排除
        exclude: /node_modules/,
        // 只坚持src下的文件
        include: path.resolve(__dirname, 'src'),
        // 优先执行 (比如这里先eslint通过之后,在babel-loader)
        enforce: 'pre',  // 'pre'优先执行   'post'延后执行
        loader: 'eslint-loader',
        options:{}
      },
      {

        // loader只会匹配一个
        // 由于只能匹配一个,所有如果下面有匹配两个js 一个做eslitn 一个做兼容处理, 需要提取一个到外面
        oneOf: [
          {
            test: /\.css$/,
            use: [
...

resolve 解析模考规则

module.exports = {
resolve: {
    // 模块路径别名 
    alias: {
      '@': path.resolve('src'),
      components: path.resolve('src/components'),
      vue$: 'vue/dist/vue.js',
    },
    // 省略文件后缀名 默认 js json
    extensions: ['.js', '.less', '.css', '.vue', '.jsx', '.scss'],
    // 告诉webpack 解析模块去哪个目录 ,比如专题项目中,每个专题文件夹直接去根目录寻找
    modules: [path.resolve(__dirname, '../../node_modules'), 'node_modules']
  },

optimization

optimization: {
    // 将当前模块记录其他模块的hash单独打包成一个文件 runtime,这样如果a引入了b文件,a文件修改的话,不会重新打包b文件,只是会修改runtime对应hash文件
    // 解决: 修改a文件导致b文件的contenthash变化
    runtimeChunk:{
      name: entrypotint => `runtime-${entrypotint.name}`
    },    
    // 代码分割
    splitChunks: {
      chunks: 'all',
      // 以下都是默认值
      // miniSize: 30*1024, // 分割最小为30kb
      // maxSize: 0 , // 最大没有限制
      // minChunks: 1, // 要提取的chunk最少被引用1次
      // maxAsyncRequests: 5, // 按需加载时并行加载的文件最大数量
      // maxInitialRequests:3, //入口js文件最大并行请求数量
      // automaticNameDelimiter: '~', // 命名连接符
      // name: true, //可以使用命名规则
      // cacheGroups:{ // 分割chunk的组
      //     // node_modules文件会被打包到vendors组的chunk中
      //     defaultVendors:{
      //       test: /[\\/]node_modules[\\/]/,
      //       priority: -10,  // 优先级
      //     }

      // },
      // default:{
      //   // 要提取的chunk最少被引用2次
      //   minChunks: 2,
      //   //优先级
      //   priority: -20,
      //   // 如果当前要打包的模块,和之前已提取的模块是同一个,就会复用,而不是重新打包
      //   reuseExistingChunk: true
      // }
    },
    minimize: true,
    minimizer: [
      // 修改 配置生产环境的压缩方案 js和css
      // 注意如果你跟我一样也是用的webpack5学习 那么需要制定版本"terser-webpack-plugin": "^4.2.3",不然打包后失败
      new TerserPlugin({
        exclude: /\/excludes/,
        // 开启缓存
        cache: true,
        // 开启多进程打包
        parallel: true,
        // 开启source-map // 如果在生产环境中使用 source-maps,必须设置为 true
        sourceMap: true
      })
    ]
  },

webpack 常用配置解析(一)
webpack 常用配置解析(二)
webpack 常用配置解析(三)

你可能感兴趣的:(webpack 常用配置解析(三))