webpack5-入门(一)

198 阅读5分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第7天,点击查看活动详情

1.1

1.1.1 为什么使用webpack

-

1.1.2 作用域问题

(function () {
  var nickname = "Tom";
})();

console.log(nickname); // Uncaught ReferenceError: nickname is not defined
var result = (function () {
  var nickname2 = "Jack";
  return nickname2;
})();

console.log(result); // Jack

1.1.3 ESM、CJS

CJS: CommonJS

  • CJS 是同步导入模块
  • CJS 不能在浏览器中工作。它必须经过转换和打包。
  • 命名导出
module.exports.sum = (x, y) => x + y;  // 导出

const {sum} = require('./util.js'); // 导入
console.log(sum(2, 4));
  • 默认导出
module.exports = (x, y) => x + y; 

const sum = require('./util.js'); 
console.log(sum(2, 4));

ESM: ES Modules

  • 在很多现代浏览器可以使用(不是所有的浏览器都支持)
  • 在浏览器使用时,修改script标签type
  • 命名导出
export const sum = (x, y) => x + y; 

import {sum} from './util.js' 
console.log(sum(2, 4));
  • 默认导出
export const sum = (x, y) => x + y; 

import {sum} from './util.js' 
console.log(sum(2, 4));
  • 在浏览器使用
<script type="module">
  import { func1 } from 'util';

  func1();
</script>

1.2

1.2.1 安装webpack

  • 必须安装nodejshttps://nodejs.org/zh-cn/
  • 安装webpacknpm i webpack webpack-cli --save-dev 不建议全局安装
  • webpack -v 检查是否安装成功

1.2.2 运行webpack

npx webpack

1.2.3 配置webpack

  • 根目录下新建一个配置文件 webpack.config.js
const path = require("path");
module.exports = {
  mode: "development", // 模式
  entry: "./src/index.js", // 打包入口地址
  output: {
    filename: "bundle.js", // 输出文件名
    path: path.join(__dirname, "dist"), // 输出文件目录
  },
};

提示:The 'mode' option has not been set,...意思是,没有配置mode(模式),提示配置一下

1.3

1.3.1 插件

  • 插件(Plugin)可以贯穿 Webpack 打包的生命周期,执行不同的任务
  • https://webpack.docschina.org/concepts/#plugins

1.3.1 HtmlWebpackPlugin

  • 安装 npm install --save-dev html-webpack-plugin
  • 文档https://github.com/jantimon/html-webpack-plugin
  • 修改webpack.config.js配置
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  mode: "development", // 模式
  entry: "./src/index.js", // 打包入口地址
  output: {
    filename: "bundle.js", // 输出文件名
    path: path.join(__dirname, "dist"), // 输出文件目录
  },
  plugins: [
    new HtmlWebpackPlugin({
      title: "管理输出", // 输出html的title, 指定template时不生效
      template: "./index.html", // 基于哪个文件生成html
      filename: "app.html", // 生成的html文件名
      inject: "body", // script标签生成到哪里
    }),
  ],
};

1.3.2 清理dist

  • /dist 文件夹会遗留了之前文件
  • clean: true 清理 /dist
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  mode: "development", // 模式
  entry: "./src/index.js", // 打包入口地址
  output: {
    filename: "bundle.js", // 输出文件名
    path: path.join(__dirname, "dist"), // 输出文件目录
    clean: true, // 清理dist
  },
  plugins: [
    new HtmlWebpackPlugin({
      title: "管理输出", // 输出html的title, 指定template时不生效
      template: "./index.html", // 基于哪个文件生成html
      filename: "app.html", // 生成的html文件名
      inject: "body", // script标签生成到哪里
    }),
  ],
};

1.4

1.4.1 mode 模式

  • development 开发模式,打包更加快速,省了代码优化步骤
  • production 生产模式,打包比较慢,会开启 tree-shaking 和 压缩代码
  • none 不使用任何默认优化选项

1.4.2 source map

当 webpack 打包源代码时,可能会很难追踪到 error(错误) 和 warning(警告) 在源代码中的原始位置。

  • devtool: 'inline-source-map'解决,浏览器控制台报错更友好
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  mode: "development", // 模式
  entry: "./src/index.js", // 打包入口地址
  output: {
    filename: "bundle.js", // 输出文件名
    path: path.join(__dirname, "dist"), // 输出文件目录
    clean: true, // 清理dist
  },
  devtool: "inline-source-map",
  plugins: [
    new HtmlWebpackPlugin({
      title: "管理输出", // 输出html的title, 指定template时不生效
      template: "./index.html", // 基于哪个文件生成html
      filename: "app.html", // 生成的html文件名
      inject: "body", // script标签生成到哪里
    }),
  ],
};

1.4.3 watch mode

  • npx webpack --watch保存文件,自动编译打包

1.4.4 webpack-dev-server

  • 安装:npm i webpack-dev-server -D
  • 文档:https://github.com/webpack/webpack-dev-server
    • 提供了一个基本的 web server
    • 具有 live reloading(实时重新加载) 功能

修改 webpack.config.js配置

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

module.exports = {
  mode: "development", // 模式
  entry: "./src/index.js", // 打包入口地址
  output: {
    filename: "bundle.js", // 输出文件名
    path: path.join(__dirname, "dist"), // 输出文件目录
    clean: true,
  },
  devtool: "inline-source-map",
  devServer: {
    static: "./dist",
  },
  plugins: [
    new HtmlWebpackPlugin({
      title: "管理输出", // 输出html的title, 指定template时不生效
      template: "./index.html", // 基于哪个文件生成html
      filename: "app.html", // 生成的html文件名
      inject: "body", // script标签生成到哪里
    }),
  ],
};

运行 npx webpack-dev-server

cyq@caiyongqingdeMacBook-Air webpack-test % npx webpack-dev-server
<i> [webpack-dev-server] Project is running at:
<i> [webpack-dev-server] Loopback: http://localhost:8080/
<i> [webpack-dev-server] On Your Network (IPv4): http://192.168.3.120:8080/
<i> [webpack-dev-server] On Your Network (IPv6): http://[fe80::1]:8080/
<i> [webpack-dev-server] Content not from webpack is served from './dist' directory
asset bundle.js 570 KiB [emitted] (name: main)
asset app.html 309 bytes [emitted]
runtime modules 27.3 KiB 12 modules
modules by path ./node_modules/ 160 KiB
modules by path ./node_modules/webpack-dev-server/client/ 55.8 KiB 12 modules
modules by path ./node_modules/webpack/hot/*.js 4.3 KiB
./node_modules/webpack/hot/dev-server.js 1.59 KiB [built] [code generated]
./node_modules/webpack/hot/log.js 1.34 KiB [built] [code generated]
+ 2 modules
modules by path ./node_modules/html-entities/lib/*.js 81.3 KiB
./node_modules/html-entities/lib/index.js 7.74 KiB [built] [code generated]
./node_modules/html-entities/lib/named-references.js 72.7 KiB [built] [code generated]
+ 2 modules
./node_modules/ansi-html-community/index.js 4.16 KiB [built] [code generated]
./node_modules/events/events.js 14.5 KiB [built] [code generated]
./src/index.js 49 bytes [built] [code generated]
webpack 5.74.0 compiled successfully in 226 ms
  • webpack-dev-server 热更新功能 可以让页面自动刷新行

遇到问题

WARNING in asset size limit: The following asset(s) exceed the recommended size limit (293 KiB).
This can impact web performance.
Assets: 
  bundle.js (585 KiB)

WARNING in entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit (488 KiB). This can impact web performance.
Entrypoints:
  main (586 KiB)
      bundle.js
      styles/af02acdb4a0028ac0250.css


WARNING in webpack performance recommendations: 
You can limit the size of your bundles by using import() or require.ensure to lazy load some parts of your application.
For more info visit https://webpack.js.org/guides/code-splitting/
module.exports = {
  //...
	performance: {
    hints:'warning',
    //入口起点的最大体积
    maxEntrypointSize: 50000000,
    //生成文件的最大体积
    maxAssetSize: 30000000,
    //只给出 js 文件的性能提示
    assetFilter: function(assetFilename) {
      return assetFilename.endsWith('.js');
    }
  },
}

1.5 Asset Modules

1.5.1 resource资源

  • 配置module

修改 webpack.config.js配置

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

module.exports = {
  mode: "development", // 模式
  entry: "./src/index.js", // 打包入口地址
  output: {
    filename: "bundle.js", // 输出文件名
    path: path.join(__dirname, "dist"), // 输出文件目录
    clean: true,
  },
  devtool: "inline-source-map",
  devServer: {
    static: "./dist",
  },
  plugins: [
    new HtmlWebpackPlugin({
      title: "管理输出", // 输出html的title, 指定template时不生效
      template: "./index.html", // 基于哪个文件生成html
      filename: "app.html", // 生成的html文件名
      inject: "body", // script标签生成到哪里
    }),
  ],
  module: {
    rules: [
      {
        test: /.(png|svg|jpg|jpeg|gif)$/i,
        type: "asset/resource",
      },
    ],
  },
};

js文件

import imgSrc from "../asset/logo.png";

// const a = 123;
// console.log(a);

let imgEle = document.createElement('img')
imgEle.src = imgSrc
document.body.appendChild(imgEle)

配置打包路径和文件名

  • 1
output: {
  filename: "bundle.js", // 输出文件名
  path: path.join(__dirname, "dist"), // 输出文件目录
  clean: true,
  assetModuleFilename: "images/[contenthash][ext]", // 配置名字和扩展名
}
  • 2
rules: [
  //...
  {
    test: /.(png|svg|jpg|jpeg|gif)$/i,
    type: "asset/resource",
    generator: {
      filename: "images/[contenthash][ext]",
    },
  },
],

generator的优先级大于output

1.5.2 inline资源

当使用asset/inline 时,打包的资源不会单独生成打包文件。

比如图片,会转成base64格式

rules: [
  //...
  {
    test: /.(png|svg|jpg|jpeg|gif)$/i,
    type: "asset/inline",
  },
],

1.5.3 source资源

  • source资源导出资源的源代码
rules: [
  //...
  {
    test: /.txt$/,
    type: "asset/source",
  },
],

1.5.4 asset通用类型

  • 通过判断选择 加载类型 (生成data URI 还是生成单独的文件)
rules: [
  {
    test: /.(png|svg|jpg|jpeg|gif)$/i,
    type: "asset",
    parser: {
      dataUrlCondition: {
        maxSize: 1024 * 10, // 大于这个值就生成单独的文件
      },
    },
  },
],