WebPack5学习笔记

23 篇文章 0 订阅
2 篇文章 0 订阅

前言

这篇文章是学习笔记类型,内容会逐级深入,看完后可以对webpack有基本认知,且可以自行对项目进行配置。

一、初步使用

1. 初始化

在项目终端输入npm init -y命令,会自动创建并初始化package.jsonREADME.en.mdREADME.md文件

npm init -y

2. 修改配置

初始化完成后,需要对内容进行修改,main后面的路径需要改成项目对应的路径

package.json

{
  "name": "study-webpack",
  "version": "1.0.0",
  "description": "webpack学习",
  "main": "./src/main.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "https://gitee.com/dream-seller-andy/study-webpack.git"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

注意:name值不能为webpack,否则会无法安装webpack

3. 安装插件

安装webpackwebpack-cli两个插件,运行以下命令

npm i webpack webpack-cli -D

4. 打包

输入npx webpack打包,因为没有配置文件,所以需要在npx webpack后面添加入口文件路径打包模式,这是最基础的打包配置,仅能转译jsjson文件,webpack5新增了可以打包图片等静态文件功能

开发模式打包,可以把es6语法编译成浏览器可识别的低版本语法,不会对文件进行压缩

npx webpack ./src/main.js --mode=development

生产模式打包,可以把es6语法编译成浏览器可识别的低版本语法,并且对文件进行压缩

npx webpack ./src/main.js --mode=production

这样,一个最基本的包就生成了

二、深入学习

准备工作里的打包方式,显然不是我们想要的,我们需要的是能够定制化的,功能更全面的,实用性更好的方式,而想要达到这个目的,就需要对webpack进行具体的配置了。

1. 基础配置

在项目根目录创建一个webpack.config.js文件,并配置相关信息

const path = require("path"); // node.js核心模块,主要用来解析路径问题

module.exports = {
  // 入口
  entry: "./src/main.js", // 相对路径
  // 出口
  output: {
    path: path.resolve(__dirname, "dist"), // 文件输出路径-绝对路径
    filename: "main.js", // 文件名-命名随意
    clean: true, // 打包前自动删除上一次打包文件
  },
  // 加载器,用来处理webpack自带不能处理的文件,webpack官网有很多loader可添加
  module: {
    rules: [],
  },
  // 插件,用来优化打包性能
  plugins: [],
  // 模式,开发模式或生成模式
  mode: "development",
};

2. Loader

webpack-loader官网配置地址

  • 注意1:所有用到的loader都需要安装,官网示例未必是完整的
  • 注意2:所有需要打包的文件都需要在main.js中先引入
  • 注意3:type后面的asset表示压缩,对于字体图标等不需要压缩的文件,需要使用asset/resource

具体配置看官网说明

css-loadersass-loader举例:

安装以下loader

npm install style-loader css-loader --save-dev 
npm install sass-loader sass webpack --save-dev

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        type: "asset",
        use: ["style-loader", "css-loader"],
      },
      {
        test: /\.s[ac]ss$/,
        type: "asset",
        use: ["style-loader", "css-loader", "sass-loader"],
      },
    ],
  },
};

这样,webpack就可以打包.css.sass.scss结尾的文件了,如需添加其它类型的文件,只需要继续在数组中添加新的对象即可,记住,一定要安装所有用到的loader

优化1:减少浏览器请求次数

把项目内体积比较小的图片文件,转换成base64格式,此方法会增加一定的图片体积,大约20%左右,不过相比较增加请求次数,这点确定还是可以接受的

webpack5已经内置了图片处理,所以不需要额外下载loader,但是需要进行配置激活

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.(png|jpe?g|svg|gif|webp)$/,
        type: "asset",
        parser: {
          dataUrlCondition: {
            maxSize: 10 * 1024, // 10kb,小于10kb会被转译成base64
          },
        },
      },
    ],
  },
};
优化2:分类输入不同类型的文件

为了打包后文件不至于太过混乱,对于不同类型的文件,分别用一个文件夹保存,这个功能需要对每种类型的文件都单独配置出口路径

webpack.config.js

module.exports = {
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "static/js/main.js",
    clean: true,
  },
  module: {
    rules: [
      {
        test: /\.(png|jpe?g|svg|gif|webp)$/,
        type: "asset",
        generator: {
          // hash:文件名不重复,且不超过10位、ext:保留后缀名、query:保留url地址中自行添加的方便搜索的?等字符
          filename: "static/images/[hash:10][ext][query]",
        },
      },
      {
        test: /\.(ttf|woff2?)$/,
        type: "asset/resourse",
        generator: {
          filename: "static/media/[hash:10][ext][query]",
        },
      },
    ],
  },
};

案例1:处理字体图标、音视频等文件

webpack.config.js

rules: [
  {
    test: /\.(ttf|woff2?|map3|map4|avi)$/,
    type: "asset/resourse",
    generator: {
      filename: "static/media/[hash:10][ext][query]",
    },
  },
],
案例2:babel-loader

作用:将ES6语法转译成ES5语法,详情可查看 babel-loader 官方文档

babel-loader 运行很慢,我们需要用一些方法来进行优化,优化的方法会在第4节:优化中进行详细去说,此处就不做赘述了

安装babel-loader

npm install -D babel-loader @babel/core @babel/preset-env webpack

webpack.config.js

rules: [
  {
    test: /\.js$/,
    exclude: /node_modules/,
    loader: "babel-loader",
  },
],

在项目根目录创建babel.config.js文件,为了方便以后管理和修改,babel-loader配置信息写在babel.config.js文件中,内容设置为只能预设,如下方展示代码

babel.config.js

module.exports = {
  presets: ["@babel/preset-env"],
};
案例3:postcss-loader

作用:处理 css 兼容性,使其兼容更多版本的浏览器, 详情可查看 postcss-loader 官方文档

安装postcss-loader

npm install postcss-loader postcss postcss-preset-env --save-dev

使用postcss-loader,因为这个模块可能会多次重复使用,为了提高代码的美观度和复用性,我们把这个模块封装成一个函数,需要使用的时候直接调用即可

webpack.prod.js

function getStyleLoader(loader) {
  return [
    MiniCssExtractPlugin.loader,
    "css-loader",
    {
      loader: "postcss-loader",
      options: {
        postcssOptions: {
          plugins: ["postcss-preset-env"],
        },
      },
    },
    loader,
  ].filter(Boolean);
}

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: getStyleLoader(),
      },
      {
        test: /\.s[ac]ss$/,
        type: "asset",
        use: getStyleLoader("sass-loader"),
      },
    ],
  },
};

package.json 文件中添加以下内容,指定需要兼容哪些浏览器,以下代码表示兼容同时满足列举出的 3 个条件的浏览器,这也是目前较为普遍使用的兼容性处理方案

  1. 99% 以上
  2. 最近两个版本
  3. 没有退市

package.json

"browserslist": [
  "> 1%",
  "last 2 versions",
  "not dead"
]

3. Plugin

实际项目开发过程中有很多插件需要用到,本文只列举其中几个进行举例

插件1:EslintWebpackPlugin

作用:用来查找和修复js代码中的问题,详情可查看
EslintWebpackPlugin 官方文档

安装eslinteslint-webpack-plugin

npm install eslint eslint-webpack-plugin --save-dev

创建.eslint.js.eslintignore文件,分别用来配置校验规则指定不校验的文件

.eslint.js

module.exports = {
  extends: ["eslint:recommended"], // 继承 Eslint 官方校验规则,也可以选择继承 vue、react 等其它校验规则
  env: {
    node: true, // 开启 node 全局变量
    browser: true, // 开启浏览器全局变量
  },
  parserOptions: {
    ecmaVersion: 6, // es6语法
    sourceType: "module", // es6模块
  },
  // 自定义规则会覆盖继承的规则
  rules: {
    "no-var": 2,
  },
  plugins: ["import"],
};

.eslintignore

dist

使用eslint-webpack-plugin

webpack.config.js

const ESLintPlugin = require('eslint-webpack-plugin');

module.exports = {
  plugins: [
    // 仅校验src目录下的文件
    new ESLintPlugin({
      context: path.resolve(__dirname, "src"),
    }),
  ],
};
插件2:HtmlWebpackPlugin

作用:自动生成一个 HTML5 文件, 并在 body 中使用 script 标签引入你所有 webpack 生成的 bundle,详情可查看 HtmlWebpackPlugin官方文档

安装HtmlWebpackPlugin

npm install --save-dev html-webpack-plugin

使用HtmlWebpackPlugin

webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  plugins: [
    // 保持和public/index.html中的文件结构一致
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, 'public/index.html')
    }),
  ],
};

提示:建议以下插件在看完 “开发模式和生产模式” 内容后再看,因为会涉及到这方面的知识点


插件3:MiniCssExtractPlugin

作用:本插件会将 CSS 提取到单独的文件中,为每个包含 CSS 的 JS 文件创建一个 CSS 文件,并且支持 CSS 和 SourceMaps 的按需加载,详情可查看 MiniCssExtractPlugin 官方文档

提示:如果不提取 csscss 会打包在 main.js 文件中

  • 注意1:本插件基于 webpack v5 的新特性构建,并且需要 webpack 5 才能正常工作
  • 注意2:将所有的 style-loader 都改成 MiniCssExtractPlugin.loader
  • 注意3:此插件仅推荐在生产模式 production 中使用,在开发模式 development 下,style-loader 拥有更快的速度,且可以使用多个标签将 CSS 插入到 DOM 中

安装 mini-css-extract-plugin

npm install --save-dev mini-css-extract-plugin

使用 mini-css-extract-plugin

webpack.prod.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
      {
        test: /\.s[ac]ss$/,
        use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
      },
    ],
  },
  plugins: [
    // 指定css文件名
    new MiniCssExtractPlugin({
      filename: "static/css/main.css",
    }),
  ],
};
插件4:CssMinimizerWebpackPlugin

作用:使用 cssnano 优化和压缩 CSS,详情可查看 CssMinimizerWebpackPlugin 官方文档

安装 css-minimizer-webpack-plugin

npm install css-minimizer-webpack-plugin --save-dev

使用 css-minimizer-webpack-plugin

webpack.prod.js

const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");

module.exports = {
  plugins: [
    new CssMinimizerPlugin()
  ]
};

配置到了这一步,其实已经可以看到效果了,这时候在项目终端输入npx webpack命令,会自动打包输入一个dist文件夹,打开文件夹里的index.html文件即可看到项目运行的效果

npx webpack

4. devServer

在配置完LoaderPlugin后,我们还需要开启前端本地服务,以方便查看效果和调试,这时候就需要配置devServer信息了

webpack.config.js

module.exports = {
  devServer: {
    host: 'localhost',
    port: '8080',
    open: true
  },
};

在添加devServer之前,我们启动项目的命令是npx webpack,但是此方法不是实时的,每次修改内容后都需要重新输入并执行命令,这显然是不利于项目开发调试的

使用了 devServer 之后,启动项目的命令变成了 npx webpack server ,这个命令不会输出 dist 文件,但是可以启动一个本地服务,在浏览器中访问这个地址 http://localhost:8080/ ,即可查看项目运行效果(也可以通过配置 open:true 来自动打开页面),此方法是实时更新的,不需要反复输入命令,每次修改保存后的内容,都会同步反映到浏览器中

npx webpack server

三、开发模式和生产模式

上面的学习已经比较全面了,但是项目在开发过程中和最终生产上线还是会有不少的区别,为了能够更精细的去管理和控制,我们需要进一步的优化

在根目录下创建config文件夹,并在此文件夹中分别创建webpack.dev.jswebpack.prod.js文件,内容与之前的webpack.config.js基本一致,部分配置需要调整

  • 调整1:所有的绝对路径都要改成相对路径
  • 调整2:webpack.dev.js中的clean:true删除,mode设置为development
  • 调整2:webpack.prod.js中的devServer模块删除,mode设置为production

以下示例只展示了修改的部分,并非是webpack.dev.jswebpack.prod.js的全部内容

webpack.dev.js

const path = require("path");
const ESLintPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: "./src/main.js", // 相对路径
  output: {
    path: undefined,
    filename: "static/js/main.js",
  },
  plugins: [
    new ESLintPlugin({
      context: path.resolve(__dirname, "../src"),
    }),
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, '../public/index.html')
    })
  ],
  devServer: {
    host: 'localhost',
    port: '8080',
    open: true
  },
  mode: "development",
};

webpack.prod.js

const path = require("path");
const ESLintPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  entry: "./src/main.js", // 相对路径
  output: {
    path: path.resolve(__dirname, "../dist"),
    filename: "static/js/main.js",
    clean: true,
  },
  plugins: [
    new ESLintPlugin({
      context: path.resolve(__dirname, "../src"),
    }),
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, "../public/index.html"),
    }),
  ],
  mode: "production",
};

四、优化

1. 非性能优化

方式1:添加源代码映射,方便定位问题

在 webpack 中配置 Devtool ,可以控制是否生成,以及如何生成 source map,当出现错误的时候,浏览器可以提示错误代码出现的位置,详细内容可查看 Devtool 官方文档

webpack.dev.js

module.exports = {
  // ...
  devtool: "cheap-module-source-map", // 只映射行,位置模糊,编译速度快
};

webpack.prod.js

module.exports = {
  // ...
  devtool: "source-map", // 映射行和列,位置精确,编译速度慢
};
方式2:js兼容性

在之前我们已经使用了 babel-loaderjs 进行了兼容性处理,但 babel-loader 并不能处理所有的兼容性,某些 ES6 新特性,是无法进行处理的,这时候我们需要借助 core-js 对遗漏部分进行补充

安装 core-js

npm install core-js@3 --save

使用 core-js

babel.config.js

module.exports = {
  presets: [
    [
      "@babel/preset-env",
      {
        useBuiltIns: "usage", // 自动按需引入
        corejs: 3, // core-js 第3版
      },
    ],
  ],
};

2. 提高编译速度

方式1:模块热更新

我们发现,在当前未作处理的情况下,每次修改内容,都会整个项目重新加载编译,如果可以让只做修改的部分重新编译,其它部分不做改变,速度就会提升很多

webpack5 默认开启热更新模块,但是默认只能编译 style-loader 中内置的样式模块 ,如果需要实现 js 热更新模块,则需要手动添加

注意:热模块更新只能用在开发环境

webpack.dev.js

module.exports = {
  // ...
  devServer: {
    // ...
    hot: true, // 也可以不写,默认为true
  },
};

在入口文件 main.js 中,将所有引入的 js 文件都设置一遍,以下代码仅为示例

main.js

import add from "./js/count.js";
import store from "./store/index.js"

// 判断是否支持热模块更新,如果支持,则重新引入
if (module.hot) {
  module.hot.accept("./js/count.js");
  module.hot.accept("./store/index.js");
}

到这里我们会有一个疑惑,如果引入的 js 文件有几百个,难道要把这几百个文件全部重新引入一遍吗?

答案是不完全正确,如果我们用传统的方式搭配 webpack 开发,确实需要全部都重新引入一遍,但是如果我们使用 vuereact 等框架开发,只需要借助 vue-loaderreact-hot-loader 即可,不需要自己一个个引入,详细内容可自行查看 webpack 模块热替换官方文档

方式2:用 oneOfloader 进行处理

我们在 module.rules 中配置了很多的 loader,每个文件要被所有的 loader 检测一遍来确定是否需要处理,但实际上每个文件只会被一个 loader 处理,当匹配到一个合适的 loader 时,根本不需要再去对剩下的 loader 进行比对,对此我们需要做一些配置

开发和生产环境下都可以进行此配置,以下代码仅为示例,并非完整代码,在 modules.rules 内 添加一个对象,在这个对象中添加一个 oneOf 的数组,把 loader 放入这个数组中即可

webpack.dev.jswebpack.prod.js

// ...
module.exports = {
  // ...
  module: {
    rules: [
      {
        // oneOf 表示以下 loader 只要有一个符合条件,其它的就不会继续执行
        oneOf: [
          {
            test: /\.css$/,
            use: ["style-loader", "css-loader"],
          },
          {
            test: /\.s[ac]ss$/,
            type: "asset",
            use: ["style-loader", "css-loader", "sass-loader"],
          },
          {
            test: /\.js$/,
            exclude: /node_modules/,
            loader: "babel-loader",
          },
        ],
      },
    ],
  },
};
方式3:限定 Loader 和 Plugins 的检测范围

通过使用 excludeinclude ,来限定 LoaderPlugins 的检测范围

exclude:除了列出模块之外,全部处理

include:只处理列出的模块

webpack.dev.jswebpack.prod.js

// ...
module.exports = {
  // ...
  module: {
    rules: [
      {
        oneOf: [
          {
            test: /\.css$/,
            // 只处理 ../src 下的文件,此处只做演示,实际开发中不需要对样式进行限制
            include: path.resolve(__dirname, "../src"), 
            use: ["style-loader", "css-loader"],
          },
          {
            test: /\.js$/,
            exclude: /node_modules/, // 除了 node_modules ,全部处理
            loader: "babel-loader",
          },
        ],
      },
    ],
  },
  plugins: [
    new ESLintPlugin({
      context: path.resolve(__dirname, "../src"),
      exclude: "node_modules", // 默认值,可写可不写
    }),
  ],
};
方式4:利用缓存

对于已经打包过的文件,我们可以将其缓存起来,再次打包的时候,未做修改的内容可以直接使用上一次缓存的文件,这样可以提高打包编译的速度

webpack.dev.jswebpack.prod.js

// ...
module.exports = {
  // ...
  module: {
    rules: [
      {
        oneOf: [
          {
            test: /\.js$/,
            exclude: /node_modules/, // 除了 node_modules ,全部处理
            loader: "babel-loader",
            options: {
              cacheDirectory: true, // 开启babel缓存
              cacheCompression: false, // 关闭缓存文件压缩
            },
          },
        ],
      },
    ],
  },
  plugins: [
    new ESLintPlugin({
      context: path.resolve(__dirname, "../src"),
      exclude: "node_modules", // 默认值,可写可不写
      cache: true, // 开启缓存
      cacheLocation: path.resolve(__dirname, "../node_modules/.cache/eslintcache"), // 指定缓存文件路径
    }),
  ],
};

如果只到这里就结束,我们会发现,当一个文件被引入多个文件中时,一旦这个文件发生改变,打包时,其它文件也会一起重新打包,为了避免这种情况产生,我们可以在 optimization 中追加配置

// ...
module.exports = {
  // ...
  // webpack5 推荐把优化配置写在这里
  optimization: {
    // 避免打包时一个文件改变影响到其它文件一起改变
    runtimeChunk: {
      name: (entrypoint) => `runtime~${entrypoint.name}.js`,
    },
  },
};
方式5:多进程打包

为了提高打包编译的速度,我们可以开启多线程同时打包,电脑 cpu 有多少核心,最多就能同时开启多少个线程,实现此功能,需要用到 thread-loader 插件,详细内容可以查看 thread-loader 官方文档

  • 注意:每开启一个线程,都要多消耗差不多 600ms 的时间,所以这个方式只推荐在项目较大,任务较多时使用
  • 注意2:thread-loader 要写在所有 loader 之前

安装 thread-loader

npm install --save-dev thread-loader

使用 thread-loader

webpack.dev.jswebpack.prod.js

const os = require("os"); // node.js核心模块
const TerserWebpackPlugin = require("terser-webpack-plugin"); // webapck内置插件,无需下载

const threads = os.cpus().length; // cpu核心数

module.exports = {
  // ...
  module: {
    rules: [
      {
        oneOf: [
          {
            test: /\.js$/,
            exclude: /node_modules/,
            use: [
              {
                loader: "thread-loader",
                options: {
                  works: threads,
                },
              },
              {
                loader: "babel-loader",
                options: {
                  cacheDirectory: true, // 开启babel缓存
                  cacheCompression: false, // 关闭缓存文件压缩
                },
              },
            ],
          },
        ],
      },
    ],
  },
  plugins: [
    new ESLintPlugin({
      context: path.resolve(__dirname, "../src"),
      exclude: "node_modules", // 默认值
      cache: true, // 开启缓存
      cacheLocation: path.resolve(__dirname, "../node_modules/.cache/eslintcache"), // 指定缓存文件路径
      threads,
    }),
  ],
  // webpack5 推荐把优化配置写在这里
  optimization: {
    minimizer: [
      new CssMinimizerPlugin(),
      new TerserWebpackPlugin({
        parallel: threads,
      }),
    ],
  },
};

3. 减小代码体积

webpack 对于未使用的 js 文件默认不会打包,但除此之外,我们还需要进行更进一步的优化

方式1:优化 babel-loader

第2节:深入学习中,我们曾提到 babel-loader 运行很慢,这是因为 Babel 对一些公共方法使用了非常小的辅助代码,比如 _extend。默认情况下会被添加到每一个需要它的文件中。

为了解决这个问题,我们可以引入 Babel runtime 作为一个独立模块,来避免重复引入

安装 @babel/plugin-transform-runtime

npm install -D @babel/plugin-transform-runtime

使用 @babel/plugin-transform-runtime

webpack.dev.jswebpack.prod.js

// ...
module.exports = {
  // ...
  module: {
    rules: [
      {
        oneOf: [
          {
            test: /\.js$/,
            exclude: /node_modules/, // 除了 node_modules ,全部处理
            loader: "babel-loader",
            options: {
              cacheDirectory: true, // 开启babel缓存
              cacheCompression: false, // 关闭缓存文件压缩
              plugins: ['@babel/plugin-transform-runtime'],
            },
          },
        ],
      },
    ],
  },
};
方式2:压缩图片

对于本地图片,我们可以对其进行压缩,为此我们需要用到 ImageMinimizerWebpackPlugin 插件

安装 image-minimizer-webpack-plugin

npm install image-minimizer-webpack-plugin imagemin --save-dev

无损压缩插件 imagemin-gifsicleimagemin-jpegtranimagemin-optipngimagemin-svgo

npm install imagemin-gifsicle imagemin-jpegtran imagemin-optipng imagemin-svgo --save-dev

有损压缩插件 imagemin-gifsicleimagemin-mozjpegimagemin-pngquantimagemin-svgo

npm install imagemin-gifsicle imagemin-mozjpeg imagemin-pngquant imagemin-svgo --save-dev

使用 image-minimizer-webpack-plugin,以无损压缩举例

webpack.prod.js

// ...
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

// ...
module.exports = {
  // ...
  // webpack5 推荐把优化配置写在这里
  optimization: {
    // 压缩配置
    minimizer: [
      // ...
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.imageminGenerate,
          options: {
            plugins: [
              ["gifsicle", { interlaced: true }],
              ["jpegtran", { progressive: true }],
              ["optipng", { optimizationLevel: 5 }],
              [
                "svgo",
                {
                  plugins: [
                    'preset-default',
                    'prefixIds',
                    {
                      name: 'sortAttrs',
                      params: {
                        xmlnsOrder: 'alphabetical'
                      }
                    }
                  ],
                },
              ],
            ],
          }
        },
      }),
    ],
  },
};

4. 提高代码运行性能

方式1:分割代码

问题:我们发现每次打包后,每个类型的文件都只会打包到一个文件中,这样在项目加载时,就会一次性加载所有同类型的代码,速度就会很慢。

解决思路:如果我们能把不同文件中的代码分别打包到不同的文件中,这样每次加载时,就会只加载当前页所用到的代码。同时,对于公共模块的代码,虽然很多文件都引入了,但是我们也只需要打包一次即可,不需要进行重复打包。

显然,webpack 当然是有这个插件的,并且本身就已经集成了,默认配置下需要达到一定体积才会被单独打包,详细内容可查看 SplitChunksPlugin 官方文档

webpack.prod.js

// ...
module.exports = {
  // ...
  output: {
    path: path.resolve(__dirname, "../dist"), // 文件输出路径-相对路径
    filename: "static/js/[name].js", // 文件名-命名随意
    chunkFilrname: "static/js/[name].js", // 其它文件打包输出的名字,沿用原文件命名
    clean: true,
  },
  optimization: {
    // 代码分割
    splitChunks: {
      chunks: "all", // 对所有模块都分割
      // 以下为默认配置
      minSize: 20000,
      minRemainingSize: 0,
      minChunks: 1,
      maxAsyncRequests: 30,
      maxInitialRequests: 30,
      enforceSizeThreshold: 50000,
      cacheGroups: {
        defaultVendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: -10,
          reuseExistingChunk: true,
        },
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true,
        },
      },
    }, 
  },
};
方式2:统一命名规范

在出口文件中追加配置,然后删除和修改 LoaderPlugin 中的 filename 配置即可,开发模式下某些没用到的插件不用配置

webpack.prod.jswebpack.prod.js

// ...
module.exports = {
  output: {
    path: path.resolve(__dirname, "../dist"), // 文件输出路径-相对路径
    filename: "static/js/[name].js", // 文件名-命名随意
    chunkFilename: "static/js/[name].chunkjs", // 自动生成命名,但是以chunk.js结尾
    assetModuleFilename: "static/media/[hash:10][ext][query]", // 图片、文字等资源按照type:assets命名
    clean: true,
  },
  module: {
    rules: [
      {
        oneOf: [
          {
            test: /\.(png|jpe?g|svg|gif|webp)$/,
            type: "asset",
            parser: {
              dataUrlCondition: {
                maxSize: 10 * 1024, // 10kb,小于10kb会被转译成base64
              },
            },
          },
          {
            test: /\.(ttf|woff2?)$/,
            type: "asset/resourse",
          },
        ],
      },
    ],
  },
  plugins: [
    // 把css单独提取出来作为独立的文件
    new MiniCssExtractPlugin({
      filename: "static/css/[name].css",
      chunkFilename: "static/css/[name].chunk.css", // 添加命名规范
    }),
  ],
};

方式3:控制加载时期(preload、prefetch)

控制当前页面需要用到的资源立即加载,暂时不用的资源在浏览器空闲时再加载,实现这个功能需要用到 @vue/preload-webpack-plugin 插件,@vue/preload-webpack-plugin 插件 git 地址

  • 注意1:preload 是立即加载,prefetch 是在浏览器空闲时加载
  • 注意2:preload 兼容性较好(完全不兼容 ie),prefetch 兼容性较差(兼容 ie11,在 Safari 中有兼容性问题)

安装 @vue/preload-webpack-plugin

npm install --save-dev @vue/preload-webpack-plugin

使用 @vue/preload-webpack-plugin

webpack.prod.js

const PreloadWebpackPlugin = require("@vue/preload-webpack-plugin");

module.exports = {
  plugins: [
    new PreloadWebpackPlugin({
      rel: "preload",
      as: "script",
    }),
  ],
};

5. 离线访问

我们项目的运行是建立在联网的情况下,如果网络断开,项目将会无法打开,这个问题,可以借助 workbox-webpack-plugin 插件来解决

安装 workbox-webpack-plugin

npm install workbox-webpack-plugin --save-dev

webpack.prod.js

const WorkboxPlugin = require('workbox-webpack-plugin');

module.exports = {
  plugins: [
    new WorkboxPlugin.GenerateSW({
      // 这些选项帮助快速启用 ServiceWorkers
      // 不允许遗留任何“旧的” ServiceWorkers
      clientsClaim: true,
      skipWaiting: true,
    }),
  ],
};

main.js

// 判断是否支持 service-worker
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);
    });
  });
}

此时我们还需要安装一个插件,这是因为 service-worker 查找的目录不是 dist下的目录,所以我们需要修改此处设定

npm install server -g

启动命令

serve dist

image.png

这时候再使用 npm run build 打包,就会发现dist中多了一些代码,有了这些代码我们就可以进行离线访问了

image.png

结束

webpack 的初步学习到此就告一段落了,后续会对文档进行不定期更新。

关于 webpack 的文章后面还会考虑单独写几篇有关优化和结合 vuereact 等框架使用分享,应该会在近期内完成。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

温其如玉_zxh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值