webpack基本用法

webpack 的 使用

前言

  • webpack 作为前端主要的模块化打包工具,我们是必然需要去掌握,理解其用法的。接下来我们就来一起学习 webpack 吧 ☺️

创建项目 webpack-project 文件夹

  • npm 或 yarn 包下载器 任选一个 我们这里就是用 yarn
  1. 我们在项目根目录 通过 yarn init -y 生成默认 package.json 包管理文件
yarn init -y
  1. 安装 webpack webpack-cli
yarn add webpack webpack-cli -D
  1. webpack 默认有打包入口和出口
打包入口 src/index.js
输出出口 dist/main.js
  1. 执行 yarn webpack 就可以生成 dist 打包目录了
webpack 或
yarn webpack
  1. webpack 执行命令 mode 默认为 production webpack 默认会帮你进行代码压缩

自定义配置 创建 webpack.congfig.js ( wepacke 会读取 webpack.config.js 配置 )

webpack 五个核心概念

  1. entry
  • 指定入口文件
  1. output
  • 输出文件,位置,文件名
  1. loader 翻译官
  • 处理非 js 文件,webpack 自身只能打包 js 或 json
    如:css,img,font,html 等一系列文件 将其打包成 js 模块
  1. plugins 压缩,版本
  • 扩展 webpack 的功能
  1. mode
  • 可以设置 development,production,none 这个详情见中文官网
  1. optimization 最佳化
  • 可以设置代码切割,树摇等一些列操作, 生产模式下自动开启
entry
// entry 可以是string,array , object 类型  这里我设为了object 既可以多入口也可单入口 😝
// 入口文件路径 如果是相对路径不可以省略 ./
entry: { bundle: "./src/index.js" },

  • 扩展

  // String 单入口 会打包生成一个默认名 main.js 的 chunk包
  entry: path.join(__dirname, "/src/index.js"),

  //Array  多入口还是会打包生成一个默认名 main.js 的 chunk包 , 主要是开发环境 html中的hmr

  entry:[path.join(__dirname, "/src/index.js"),path.join(__dirname, "/src/test.js")]
  //Object 生成多个chunk
  entry: {
    index: path.join(__dirname, "/src/index.js"),
    test: path.join(__dirname, "/src/test.js"),
  },

  // 特殊用法 就是object和array 相结合
  在dll中  vue vue-router vuex 可以打包成一个chunk模块
  entry:{
    index:[path.join(__dirname, "/src/index.js"),path.join(__dirname, "/src/add.js")]
    test: path.join(__dirname, "/src/test.js"),
  }
output
 //出口文件配置
output: {
  //输出的路径,当前项目更路径生成dist目录
  path: path.resolve(__dirname, "dist"),
  //输出的文件名称 dist/js/bundle.js
  filename: "js/[name].js",
  // 模块资源引用路径  通常 dist 会放在服务器端 作为文件更路径 👌
  publicPath: "/",
},
  • 扩展
  output: {
    // 文件位置/文件名
    filename: "js/[name].[contenthash:6].build.js",
    // 所有资源的公共目录位置
    path: path.join(__dirname, "dist"),
    //所有资源的公共路径
    publicPath: "/",
    // 拆分的chunk命名规则
    chunkFilename:[name]_chunk.js,
    //chunk暴露的变量
    library: [name],
    //变量名添加到那个对象上 window commonjs global umd
    libraryTarget: "umd",
  },

loader
module:{
  rules:[
    // 添加各种静态资源模块文件
    ... loaders
  ]
}

css 文件解析加载
  1. css-loader 将 css 文件转成 js 模块
yarn add css-loader -D
  1. style-loader 将 js 模块中的 css 标识 创建 style 标签插入
yarn add style-loader -D

  • 基本用法
{
  // 要匹配的文件名
  test: /\.css$/,
  use: [
    //从下往上执行
    // 创建style标签会将 下面的js文件插入进去 ,放在head标签中
    "style-loader",
    //将css 文件变成commonJs模块加载js中  样式字符串
    "css-loader",
  ],
},

字体,图片 文件解析加载
  1. file-loader 就是将文件复制到了指定目录
yarn add file-loader -D

  • 基本用法
{
  test: /\.(otf|eot|svg|ttf|woff|woff2)(\?\S*)?$/,
  loader: "file-loader",
  options: {
    // 输出目录
    outputPath: "fonts",
  },
},

处理图片 转成 base64 减小服务器压力,增加包的体积, 一般我们处理 4k 以下的小图片 超过 4k 会类似 file-loader 一样导出文件
yarn add url-loader -D
  • 基本用法
{
  test: /\.(png|jpg|gif)$/,
  use: [
    {
      loader: "url-loader",
      options: {
        limit: 4 * 1024,
        // 图片的路径 hash8位,后缀名
        name: "[name].[hash:8].[ext]",
        //打包输出的地址
        outputPath: "img",
        //使用commonJs 解析, 新版无需添加 😬
        esModule: false,
      },
    },
  ],
},

处理 html 文件 解析 html 文件中的 img src a href 等( 新版本有点兼容问题,我这用 1.3.2 版本的 😺)
yarn add html-loader@1.3.2 -D

  • 基本用法
{
  test: /\.(html)$/,
  use: [
      {
        loader: "html-loader",
        options: {
          esModule: false,
          attributes: {
        list: [
            {
              tag: "img",
              attribute: "src",
              type: "src",
            },
            {
              tag: "img",
              attribute: "data-src",
              type: "src",
            },
            {
              tag: "img",
              attribute: "data-srcset",
              type: "srcset",
            },
            {
              tag: "a",
              attribute: "href",
              type: "src",
            },
          ],
        },
      },
    },
  ],
},
es6 语法装 es6 ,兼容老版本浏览器,不能识别 es6 语法
yarn add babel-loader @babel/core @babel/preset-env -D

  • 基本用法
{
  test: /\.js$/,
  exclude: /(node_modules|bower_components)/,
  use: {
    loader: 'babel-loader',
    options: {
      presets: ['@babel/preset-env']
    }
  }
}
  • 扩展 (生产兼容)

以上只是解决了部分 兼容性问题 碰到 ie 这种狗比浏览器 有些还是有问题 如 Promise

  1. 暴力解决 全部 js 兼容性问题 缺点打包后的体积变大
yarn add @babel/polyfill -D

无需配置 直接 esmodule 导入即可

import "@babel/polyfill"

  1. 按需加载 core-js
yarn add core-js -D
  • 这里我配置了一些基本浏览器的参数,兼容版本
{
  test: /\.js$/,
  exclude: /(node_modules|bower_components)/,
  use: [
    //放在某个loader的后面
    // 启动时间600ms ,通信时间也要
    // 所以不是必要,别滥用
    {
      loader: "thread-loader",
      options: {
        worker: 2, //开启进程两个
      },
    },
    {
    loader: 'babel-loader',
    options: {
      // 开启babel 缓存
      // 第二次构建后,会读取之前的缓存
      cacheDirectory: true,
      presets: [
        [
          '@babel/preset-env',
          {
            // 按需加载
            useBuiltIns: "usage",
            // 指定core-js的版本
            corejs: {
              version: 3,
            },
            //指定兼容浏览器的版本
            targets: {
              chrome: "60",
              firefox: "60",
              ie: "9",
              safari: "10",
              edge: "17",
            },
          }
        ]
      ]
    }
  }
]
}

总结理解 loader 的工作原理
  • loader 就是讲匹配到的资源文件,进行一些的处理,返回 js 字符串代码,统一打包到 js 模块中

  • 接下来我们来自定义一个 loader

  1. 我们要将一个 hello_markdown.md 文件中的内容进行解析
  2. 项目根目录下创建一个 markdown-loader.js 文件
  3. 安装一个 marked,用来解析 markdown 文件
  4. return 返回的必须是 js 的字符串格式
  5. 总结 loader 就是处理资源文件数据的一个个管道
yarn add marked -D
const marked = require("marked");
module.exports = (source) => {
  let html = marked(source);
  // 直接导出
  // return `module.exports = ${JSON.stringify(html)} `;
  // return `export default ${JSON.stringify(html)} `;
  // 在通过 html-loader 处理
  return html;
};
  • 基本用法
{
 test: /\.md$/,
  use: [
      // 直接导出,不需要html-loader 再次处理
      "html-loader",
      {
        loader: "./markdown-loader",
      },
    ],
},
plugins(插件))
plugins:[
  ...
]

clean-webpack-plugin 打包时自动清除上一个 dist
yarn add clean-webpack-plugin -D
  • 基本用法
//用于在构建前清除dist目录中的内容
const { CleanWebpackPlugin } = require("clean-webpack-plugin");

plugins:[
  new CleanWebpackPlugin()
]

html-webpack-plugin 打包时自动帮你生成 html 模版 并引入 link css 打包后的 js
yarn add html-webpack-plugin -D
  1. 这里的 html-webpack-plugin 自定义变量会与 html-loader 冲突 导致 不能输出变量 大坑啊!!! 🤷‍♀️ 文章参考
  2. 好在 vue,react 这些项目中也不会去使用 ejs 语法 ,我这边就不把 html-loader 去掉了或者不用自定义变量 也没什么卵用
  3. 解决方法 1.去掉 html-loader 2.不用 ejs 字面量
  • 基本使用
//复制 html文件 并自动注册打包后 js文件
const HtmlWebpackPlugin = require("html-webpack-plugin");

plugins:[
  new HtmlWebpackPlugin({
    // 自定义变量
    // title:'my webpack'
    // 自定模块
    template: "./public/index.html",
  }),
]
copy-webpack-plugin 打包复制静态资源 就是不需要经过 loader 处理的资源文件
yarn add copy-webpack-plugin -D
  • 基本使用
const CopyWebpackPlugin = require("copy-webpack-plugin");

new CopyWebpackPlugin({
  patterns: [
    {
      from: path.resolve(__dirname, "public/static"),
      to: path.join(__dirname, "dist/static"),
    },
  ],
}),
webpack.DefinePlugin 全局注入变量, 不同环境,可以设置不同的服务器地址
  • 基本使用
let env = {
  title:'标题'
}
const webpack = require("webpack");

new webpack.DefinePlugin({
  env: JSON.stringify(env),
}),
webpackbar 打包进度条插件
yarn add webpackbar -D
  • 基本使用
const WebpackBar = require("webpackbar");
// 添加 进度条
new WebpackBar(),
webpack-merge webpack 配置合并
  • 基本使用
const { merge } = require("webpack-merge");

module.exports = merge(base,{
  ....
})
总结理解 plugins 的工作原理
  • plugins 相比于 loader 能力更强 loader 只是在加载模块时进行工作 😺

  • 接下来我们来自定义一个 plugins

  1. webpack 在处理文件时 定义了一系列的钩子,我们可以在不同的钩子节点中去扩展我们的插件
  2. 我们现在根目录下定义一个 my-plugin.js 文件
// 自定义插件
module.exports = function () {
  // wepack 会去执行实例化对象中的 apply 方法
  this.apply = function (compiler) {
    // 文件即将要输出的钩子函数
    compiler.hooks.emit.tap("MyPlugin", (compilation) => {
      for (const name in compilation.assets) {
        if (name.endsWith(".js")) {
          let content = compilation.assets[name].source();
          content = content.replace(/\/\*\*+\*\//g, "");
          compilation.assets[name] = {
            source() {
              return content;
            },
            size() {
              return content.size;
            },
          };
        }
      }
    });
  };
};

基本使用

const MyPlugin = require("./myPlugins.js");

new MyPlugin(),
optimization(最佳性能优化)
  • 扩展
  // 代码分割
  optimization: {
    splitChunks: {
      chunks: "all",
      //---------------以下都是默认值--------------
      //最小拆分大小 30kb
      minSize: 30 * 1024,
      //最大没有限制
      maxSize: 0,
      //要提取的Chunk最少一次
      minChunks: 1,
      // 按需加载时候最大的并行请求数
      maxAsyncRequests: 5,
      //一个入口最大的并行请求数
      maxInitialRequests: 3,
      // 文件名称分隔符号~
      automaticNameDelimiter: "~",
      //可以使用命名规则
      name: true,
      cacheGroups: {
        //分割chunk租
        //node_modules文件会被打包到 vendors 组中的chunk vendors.XXX.js
        vendors: {
          test: /[\\/]node_modules[\\/]/, //匹配规则
          priority: -10, //优先级
        },
        default: {
          minChunks: 2,
          priority: -20, //优先级
          reuseExistingChunk: true, //是否复用存在的chunk
        },
      },
    },
  },

这里有个小问题关于缓存的

拆分后可能,某个文件发生变化,关联文件也会变化,导致缓存失效

  // 拆分的chunk命名规则
  chunkFilename: "[name].[contenthash:6]_chunk.js",

  // 代码分割
  optimization: {
    runtimeChunk: {
      name: (h) => `runtime_${h.name}`,
    },
  },
resolve
  resolve: {
    //路径别名, 缺点,vscode 找文件不好找了 🤷‍♀️
    alias: {
      Utilities: path.resolve(__dirname, "src/utilities/"),
      Templates: path.resolve(__dirname, "src/templates/"),
    },
    //忽略后缀名
    extensions: [".js", ".json", ".css"],

    //指定modules
    modules: ["node_modules"]
  },

开发环境 提高开发效率 (打包速度快,方便调试)

通过 webpack 自带的 watch 对开发文件进行监视,变动立即打包,
yarn webpack --watch

通过 vscode 插件 Live Server 开启打包文件监视刷新

  • 总结这种虽然实现了文件打包,刷新 但是打包读写磁盘效率太低,配置麻烦
webpack-dev-server 开发服务器 内置热更新
HMR 热模块替换
  1. 优化打包速度 HMR 热模块替换 作用是一个模块发生变化时候,不会刷新浏览器,导致其他文件内容丢失

  2. 样式文件:可以使用 HMR 功能 自带的 style-loader 内部实现了

  3. js 文件:默认不能使用 HMR 功能
    html 文件:默认不能使用 HMR 功能,同时会导致问题:HTML 文件不能热更新
    :修改 entry 入口,HTML 文件加入到 spa 中不同 mpa 中不同

  4. 在 devServer 中添加 hot:true 开启 HMR 功能

  5. 现在 vue,react 等脚手架为什么可以自动热更新呢?(`ヘ ´)=3

  6. js 热更新是没有规律的, vue,react 文件导出都做了规定,导出函数,导出类 这样就确定了规范

// 处理js模块不能热更新
if(module.hot){
  module.hot.accept('js文件',()=>{
    //执行方法
  })
}
// 创建静态服务器   进行webpack 命令打包到内存中
devServer: {
      proxy: {
        "/apis": {
          target: "http://8.209.246.174:10000/",
          changeOrigin: true, // 如果接口跨域,需要进行这个参数配置
          //ws: true, // proxy websockets
          //pathRewrite方法重写url
          pathRewrite: {
            "^/apis": "/apis",
          },
        },
      },
  //静态资源目录
  contentBase: "./public",
  //gzip 压缩
  compress: true,
  //端口号
  port: 4000,
  //热更新,不需要刷新浏览器 大大提高开发速度    hot 跟 hotOnly  hotOnly 热替换失败不会自动刷新便于找到问题
  hotOnly: true,
  //开启
  open: false,
},

  • 扩展
  1. 由于配置了 mini-css-extract-plugin 不使用 style-loader 会导致 css 不热更新

解决方法: 开发环境用 style-loader 生产用 MiniCssExtractPlugin.loader (〃>皿<)

  1. devSever 详细配置
devServer: {
  // 文件目录
  contentBase: path.join(__dirname, "dist"),
  //监视文件目录
  watchContentBase: true
  //监听配置
  watchOptions: {
      poll: true,
      //忽略node_modules变动更新
      ignored: /node_modules/,
  },
  //开启文件gzip压缩加载速度更快
  compress: true,
  //端口号9000
  port: 9000,
  //host:localhost
  host: "localhost",
  //开启热替换
  hot: true,
  //自动启动浏览器
  open: true,
  //取消错误日志
  clientLogLevel: "none"
  //除了初始启动信息之外的任何内容都不会被打印到控制台
  quiet: true,
  //出现错误,不要满屏提示
  overlay: true
  //代理
  proxy: {
    "/api": {
      //ajax 请求服务器
      target: "http://localhost:3000",
      //重写
      pathRewrite: {"^/api" : ""}
    }
  }
}
souce-map 源代码地图调试
  • souce-map:一种 提供源代码到构建后 代码映射拘束(简单的说构建后代码出错了,通过映射可以追踪源代码)

  • 开启方式也十分简单

我们针对开发环境下, 速度快,查看,调试方便

devtool:'eval-source-map'

生产环境 不要暴露源代码

devtool: "nosources-source-map"

生产环境 提高运行效率 (打包速度快,性能高)

mini-css-extract-plugin 将 css 单独打包出来,较小包的体积( 文件>150kb css 文件多,内容多时使用,不然浪费一次请求时间) 一般项目都超过 150k 所以算是生产环境优化吧 😜
  1. 由于 css 是嵌入在 js 中的,加载 js 才会创建 style 标签插入 head 中 会出现闪屏现象
    作用: 减小 build.js 体积 解决闪屏现象
yarn add mini-css-extract-plugin -D
  • 基本使用
// css 分离 较小包的体积
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

// loader 配置
{
  // 要匹配的文件名
  test: /\.css$/,
    use: [
      // 不需要style-loader 去生产style标签了,去你丫的 🙆‍♂️
      {
        loader: MiniCssExtractPlugin.loader,
      options: {
        // 可以设置 css 图片引用的值 如http请求
        // publicPath: "/img/",
      },
    //将css 文件变成commonJs模块加载js中  样式字符串
    "css-loader",
  ],
},

// plugins 配置

new MiniCssExtractPlugin({
  filename: "css/[hash:8].[name].css",
}),

postcss-loader postcss-preset-env 解决大部分浏览器 css3 兼容性问题 如 -webkit-backface-visibility: hidden;
  1. postcss官网
  2. browserslist官网
yarn add postcss-loader@3 postcss-preset-env -D
  • 基本使用
 // 因为都是处理css 文件 所以又要动css的loader了 凸(艹皿艹 )
{
  // 要匹配的文件名
  test: /\.css$/,
    use: [
      // 不需要style-loader 去生产style标签了,去你丫的 🙆‍♂️
      {
        loader: MiniCssExtractPlugin.loader,
      options: {
        // 可以设置 css 图片引用的值 如http请求
        // publicPath: "/img/",
      },
    //将css 文件变成commonJs模块加载js中  样式字符串
    "css-loader",
    // css 兼容性处理
    // 会自动读取 package.json 中的文件
    // package.json 配置
    // "browserslist": {
    //   "development": [
          //   "last 1 chrome version",
          //   "last 1 firefox version",
          //   "last 1 safari version"
          //   ],
          //   "production": [
          //   "> 0.2%",
          //   "not dead"
          //   ]
          //   }
     {
       loader: "postcss-loader",
        options: {
          ident: "postcss",
          plugins: () => [
            //postcss插件  帮postcss找到package.json browerslist
              require("postcss-preset-env")(),
          ],
        },
     },
  ],
},

webpack5 以上 使用 optimize-css-assets-webpack-plugin 单独的 css 文件进行压缩处理
  1. 温馨提示 webpack5 以下使用 css-minimizer-webpack-plugin
yarn add optimize-css-assets-webpack-plugin -D
  • 基本使用
const OptimizeCssAssetsWebpackPlugin = require("optimize-css-assets-webpack-plugin");

// 在 plugins 添加
new OptimizeCssAssetsWebpackPlugin(),
eslint 规范代码风格 ( 个人还是喜欢 团队规范代码风格 )
yarn add eslint-loader eslint -D
  • 基本使用
{
  test: /\.js$/,
  exclude: /node_modules/,
  loader: 'eslint-loader',
  //优先执行 //babel-loader 转换后后执行的话会报错
  enforce: "pre",
  options: {
  // 自动修复 eslint 错误
    fix: true,
  },
},
  • 配置规范 artbnb eslint-config-airbnb-base 官网

yarn add eslint-plugin-import -D
yarn add eslint-config-airbnb-base -D

在 package.json 中配置 使用 artbnb 规范

"eslintConfig": {
  "extends":"artbnb-base",
  "env":{
    "browser":true
  }
}

压缩 html 文件
  • 新版 mode 为 production 自动压缩
  • 旧版 html-webpack-plugin,需如下配置
new HtmlWebpackPlugin({
    // 复制模版
    template: "./public/index.html",
    minify:{
      // 删除空格
      collapseWhitespace:true,
      // 去除注释
      removeComments:true
    }
}),
oneOf loader 只命中一次就结束,不用每个都去过一遍,提高打包构建速度

基本使用

rules:[
  //每次都会执行
  ...loaders
  {
    // 命中就执行
    oneOf:[
      ...loaders
    ]
  }
]

缓存
babel 缓存 (开发,生产打包优化)
  • 试想一下 如果我只改动了一个 js 模块,导致全部的 js 文件在重新构建打包一下,势必会导致打包速度的减慢,所以我们需要缓存,将只编译一个文件替换就行

详情见 bable loader
添加一下配置

 cacheDirectory: true,
文件资源缓存 (上线优化)
  • 需要去了解一下,强缓存和协商缓存的概念点击了解

  • 需要用过服务端去设置

  • 不管后端, 我们前端需要做的当文件发生修改时生成不同的文件就行,这样浏览器就会再次请求新的文件

  • 解决 文件资源缓存

  1. 通过 hash 的方式,我们虽然可以获取最新的文件,但是有些 css 文件没有修改同样也进行了更新
    (这种就是,变了一个文件,所以文件名都变了,相当于就没有缓存的效果了)

  2. 通过 chunkhash 也可以生成不同的 hash 值,来更新文件,但是 如果 css 在同一个 chunk 中还是一样会被更新
    (这种就是,变了一个文件,在同一个 chunk 中的文件 也会变)

  3. 通过 contenthash 根据文件的内容来生成 hash 值
    (这种就是,变了一个文件,只改该文件,以及连带文件,效果最好)

  • 总结
    1. 前端文件增加了 hash 当文件发生变化时,再次刷新浏览器,就会获取新的资源文件
    2. 这里我发现 通过 url-loader 转换 base64 居然有缓存,我把它改成 hash,就好了,奇怪了 凸(艹皿艹 ) 🤷‍♀️
tree shaking(树摇) 删除我们无用的代码 必须 es6Module(减小包的体积)
optimization: {
    // 树摇功能,标记 commonJs打包不导入的文件
    usedExports: true,
    // 摇下来 哪些不导出的代码
    minimize: true,
    // 合并函数,尽可能将模块合并到同一个执行函数中,又提高运行效率
    concatenateModules:true
},

1.这里要解析一下什么是文件的副副作用

打个比方

import '../index.css'
import 'xxx.js'

以上直接通过 import ‘…/xx’ 进来都会被摇调
在 package.json 文件中

'sideEffects':['xxx.js',"*css"] // fasle 全部文件无副作用 一般不可能 ,这里我直接设置true 😺
code split 代码分割 按需加载 (资源太大也不行,加载慢, 太小,http 并发请求太多。浪费带宽)
多页面打包 抽取公共部分
  • webpack 可以多页面打包
entry: {
  page1: "./src/page1.js"
  page2: "./src/page2.js"
},
output:{
  filename:[name].[contenthash:8].bundle.js
}

new HtmlWebpackPlugin({
  title: "page1",
  filename: "page1.html",
  template: "./public/index.html",
}),

new HtmlWebpackPlugin({
  title: "page2",
  filename: "page2.html",
  template: "./public/index.html",
}),

设想一下 如果 page1.js,page12.js 都引入了 jquery ,那两个包的体积都包含了 jquery
我们是否可以将 jquery 提取出来 成为一个公共的模块,在分别引入这两个 html 中? 👌

optimization: {
  splitChunks: {
    chunks: "all",
  },
}
动态加载 import(‘xxxx’)

这个是老朋友了 vue 中的路由懒加载不就是这个嘛

// 5s 后请求加载该资源文件
setTimeout(() => {
  import(/* webpackChunkName:"module" */"./module.js"
}, 5000);

魔法注释 分包名称

/* webpackChunkName:"module" */
  • 打包编译之后 5s 后 通过 script 标签去请求该 js 文件
懒加载和预加载
懒加载作用顾名思义 就是我要用是加载

需要结合上面的代码分割技术

btn.onclick = () => {
  import(/* webpackChunkName: 'hmr'*/ "./hmr.js").then(
    (res) => {
      console.log(res.default);
    }
  );
};

预加载 移动端兼容性较差 过几年应该可以使用 (项目中有一个比较大的模块,我们可以进行预加载)

webpackPrefetch: true 预加载移动端兼容性较差

btn.onclick = () => {
  import(/* webpackChunkName: 'hmr', webpackPrefetch: true*/ "./hmr.js").then(
    (res) => {
      console.log(res.default);
    }
  );
};

PWA 渐进式网络开发应用程序 (离线缓存技术)

在 webpack 中要想使用该技术要用到一个插件 运行条件:必须在服务器上

yarn add workbox-webpack-plugin -D
  • 基本使用
const WorkboxWebpackPlugin = require("workbox-webpack-plugin");

//在 plugins添加 会自动帮你 生成 service-worker.js 文件
new WorkboxWebpackPlugin.GenerateSW({
      /*
       * 1.帮助serviceworker 快速启动
       * 2.输出旧的serviceworker
       * 生成serviceworker.js 文件
       */
    clientsClaim: true,
    skipWaiting: true,
}),

在 index.js 文件中注册 service-worker.js

if ("serviceWorker" in navigator) {
  window.addEventListener("load", () => {
    navigator.serviceWorker
      .register("/service-worker.js")
      .then(() => {
        console.log("注册成功");
      })
      .catch((err) => {
        console.log("注册失败");
      });
  });
}

多进程打包 适用项目体积大的时候使用,加快打包速度

js 运行时单线程的

需要下载一个 loader thread-loader

yarn add thread-loader -D

  • 基本使用
    详情见 bable loader
    添加一下配置
//放在某个loader的后面
// 启动时间600ms ,通信时间也要
// 所以不是必要,别滥用
{
  loader: "thread-loader",
  options: {
    worker: 2, //开启进程两个
  },
},

忽略要打包的 node_module 中的库 减小打包体积 多数采用 cdn 加速引入

在 webpack.config.js 中添加 externals

  //去除打包node_module中库
  externals: {
    // 忽略库名  npm包名
    jquery: "jQuery",
  },
dll 忽略要打包的 node_module 中的库 将 node_module 中的库文件单独打包出来,不用 cdn 引入 不建议这样使用 还是 cdn 引入好
  1. 项目根目录创建 webpack.dll.js 这里我们就单独打包出来了 jquery.js,jquery.json, bootstrap.js ,bootstrap.json
const path = require("path");
const webpack = require("webpack");
module.exports = {
  // 单入口
  entry: {
    // 要打包的库是jquery
    jquery: ["jquery"],
    bootstrap: ["bootstrap"],
  },

  //出口
  output: {
    // 位置
    path: path.resolve(__dirname, "dll"),
    // 文件名
    filename: "[name].js",
    library: "[name]_[hash:10]", //打包的库里面向外暴露出去的名字是什么
  },

  //插件
  plugins: [
    new webpack.DllPlugin({
      name: "[name]_[hash:10]",
      path: path.resolve(__dirname, "dll/[name].json"),
    }),
  ],
  mode: "production", // development || production   可以在--mode=  层级更高指定
};


  1. 接着在 webpack.config.js plugins 添加 告诉 webpack 哪些库不用打包 同时名字也要变
const webpack = require("webpack");

    new webpack.DllReferencePlugin({
      manifest: path.resolve(__dirname, "dll/jquery.json"),
    }),
    new webpack.DllReferencePlugin({
      manifest: path.resolve(__dirname, "dll/bootstrap.json"),
    }),

由于忽略了 jquery bootstrap 需要引入 dll 文件夹中的两个文件

  1. 这里我们需要一个插件 add-asset-html-webpack-plugin
    将打包出去的文件引进来,在 html 中引入
yarn add add-asset-html-webpack-plugin -D
  1. 接着在 webpack.config.js plugins 添加
    // 将打包出去的文件引进来,
    new AddAssetHtmlWebpackPlugin({
      filepath: path.resolve(__dirname, "dll/jquery.js"),
    }),
    // 将打包出去的文件引进来,在html中引入
    new AddAssetHtmlWebpackPlugin({
      filepath: path.resolve(__dirname, "dll/bootstrap.js"),
    }),

  1. 这样第一次打包会将 dll 文件夹中 jquery,bootstrap 打包到 dist 文件夹中
    并且生成了 script 标签自动引入,打包第二次不会加载
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值