从0彻底整理,2024年webpack5最佳实践(附demo示例)

前言

webpack 被称为是一个模块打包机,用来做前端代码构建,能够说是一只劳绩赫赫的,在曩昔的十年里,弥补了传统前端范畴的短板,是现代前端开展真正的基石。

webpack 是前端构建东西链中的一部分,可是所谓【构建】,其完结已脱离传统前端技能的范畴了(能够说是现在广义前端的一部分,毕竟万物皆可大前端),尽管感觉上与前端开发密不行分,但事实上现已算是别的一个技能范畴了。

所以它需求你有一些相关的基础常识才干了解,假如你还没了解过相关概念,没有服务端操作系统最根本的常识,没用过nodejs或其他服务端言语,那主张你能够从更基础的概念类的技能文章看起。

现在现已快到2024年,本篇文章首要介绍下,对照webpack5最新的文档,重新整理下 webpack 的最新的最佳实践。

我会从头用 webpack 装备一个 React 项目,满意大大都情况下全面而灵敏的项目构建,相关 demo 上传到 github 上,地址:webpack_demo

我将尽力确保这是一份最简洁明了的装备,标示每一项装备呈现的原因,不会有冗余、模糊、过期的部分

本文篇幅较长,期望你有所收成。

注:尽管 node 常运用 commonJs ,但本篇代码将选用 ESM(import) 模块化规则编写

纲要

  • 前言
  • 纲要
  • 学 webpack 的必要性
  • 第一步:npm run 什么?
  • 构建流程
  • 根本装备
  • entry进口 & output出口
  • Loader 装备
  • Plugin 装备
  • Babel 编译
  • Dev Server 开发服务器
  • 资源途径引进问题
  • 一共用到了多少个包
  • 总结

学 webpack 的必要性

webpack 作为现代前端东西链的中心,功用是极为丰富、灵敏和敞开的,但一同 webpack 的文档也是极为冗杂的,尽管 webpack5 的集成现已十分强大,根本上现已能够做到开箱即用,可是构建的产品将直接用于前端成果的交付,假如你是一个技能担任人,那理清从事务代码到构建产品这个进程 webpack 都做了什么,是十分有必要的。

并且,一个项目怎样构建这其实与详细的事务场景休戚相关,很难做到开箱即用百分百适宜,技能担任人依据事务特色去自界说一套符合团队标准的构建流程,是很有必要的。

一同,了解 webpack 构建也便于你调试在构建进程中呈现的一些问题。所以即便并不影响你日常开发,最好你也要了解相关常识。

第一步:npm run 什么?

开端建立 webpack 第一件事并不是装备 entry 而是你要知道,每次发动项目时,到底在 npm run ...什么?

我觉得从这儿开端,关于并不是很了解 webpack 的人来说,心智担负就开端体现出来了,由于 webpack 供给了既黑盒又敞开的多种履行办法,这儿首要触及到三个 webpack 最常用的包 webpackwebpack-cliwebpack-dev-server

  • webpack 是一切构建的中心逻辑,必不行少
  • webpack-cli 是基于 webpack 供给的一套快捷式指令履行东西,没有更多的功用,可用可不用,推荐不用
  • webpack-dev-server 是在 webpack 之上专门用于开发环境的包,他一部分功用依靠 webpack ,一部分功用依靠 webpack-dev-middleware,既供给了node api 也供给了指令履行,一般情况也是必不行少的。

所以咱们常常翻开一个项目的package.json,会看到 npm run start/build指令后边履行的逻辑或许是 webpack 指令,或许是 webpack-dev-server 指令,或许是 node js文件的指令。其实无论用什么写法,终究都是履行的 node.js 办法。

所以,既然咱们挑选自己构建一套 webpack 装备了,咱们在 package.json 装备指令的时分就直接,用最简略的办法写一个 node.js 的履行进口,传一个参数区分出产和开发环境,一切的履行逻辑一致写在 node.js 中就好了,不要穿插运用,看起来会有点厌恶。

总归,假如不能运用彻底集成的功用,我觉得就没必要用cli指令。

能够写成:

// package.json
"scripts": {
   "start": "NODE_ENV=development node build",
   "build": "NODE_ENV=production node build"
 }

而不要:

// package.json
"scripts": {
   "start": "cross-env NODE_ENV=development webpack-dev-server --progress --config build/dev.js",
   "build": "cross-env NODE_ENV=production webpack build --config ./webpack.config.js --stats verbose"
 }

构建流程

目录划分

development(开发环境)production(出产环境) 这两个环境下的构建方针存在着巨大差异,他们的装备原则上其实应该是两份,所以咱们应该创立两个文件来别离构建开发 webpack.dev.js 和出产webpack.prod.js两种环境。

一同 webpack 装备也会有许多重复的部分,所以咱们抽离一个公共装备文件 webpack.common.js,去写通用的装备。

webpack 装备并非一个普通目标,所以咱们会用到一个 webpack 装备兼并的包 webpack-merge,来专门将公共装备兼并起来。

咱们创立build/目录,用于放构建相关的代码,创立src/目录,用于放被构建的事务代码。

从0彻底整理,2024年webpack5最佳实践(附demo示例)

履行进口

当履行npm run start/build 时,一致履行 build/index.js 文件,经过传递的环境变量 NODE_ENV 确定是履行开发环境构建仍是出产环境构建

// build/index.js
import devServer from './webpack.dev.js'
import build from './webpack.prod.js'
const { NODE_ENV = 'development' } = process.env;
console.log('当时环境:' + NODE_ENV)
NODE_ENV === 'development' ? devServer() : build()

履行 build 代码,不运用 webpack-cli的 webpack 指令,webpack 在 node 中的 api 也相同很简略,便是直接履行 webpack 办法,第一个参数是装备,第二个参数是履行成果的回调,只有传入第二个参数,build 才会立即履行。

// build/webpack.prod.js
import { merge } from 'webpack-merge'
import common from './webpack.common.js'
import webpack from 'webpack'
const webpackConfig = merge(common, {
  mode: 'production'
});
export default function () {
  // 履行build办法,开端构建
  webpack(webpackConfig, (err, stats) => {
    if (err || stats.hasErrors()) {
      console.error('编译出错')
    } else {
      console.log('webpack 编译成功')
    }
  });
}

履行 devServer 办法,咱们这儿选用 webpack-dev-server,来构建敞开环境,履行杂乱一点需求先创立 devServer 目标,如下代码

履行后webpack-dev-server会在本地启一个开发服务器,完结项目的构建、主动渲染与热更新

// build/webpack.dev.js
import { merge } from 'webpack-merge'
import common from './webpack.common.js'
import webpack from 'webpack'
import WebpackDevServer from 'webpack-dev-server'
const webpackConfig = merge(common, {
  mode: 'development',
  devServer: {
			....
  }
});
export default function () {
  // 创立webpack目标
  const compiler = webpack(webpackConfig)
  // 创立devServer目标
  const devServer = new WebpackDevServer({ ...webpackConfig.devServer }, compiler);
  const runServer = async () => {
    console.log('Starting server...');
    await devServer.start();
  };
  runServer()
}

到此,一个简略的 webpack 构建流程的根本框架就建立起来了。

根本装备

  • mode,当时环境,分为 development 开发环境和 production 出产环境两种,在 webpack 许多默许构建行为中,两种环境下的构建办法差异极大
  • devtool:挑选一种 source map 风格来增强调试进程,提示越详细打包越慢,产品越大,很明显你需求依据开发和出产两种环境,别离装备 source map 风格,你需求依据你地点的事务特色来做平衡,比方你是一个很计较性能的C端事务,那打包产品要尽或许小,假如没那么敏感能够恰当添加 source-map 细节,便于调试。
// build/webpack.dev.js
export default {
	mode: 'development',
  devtool: 'inline-source-map',
}
// build/webpack.prod.js
export default {
	mode: 'production',
  devtool: 'source-map',
}

entry进口 & output出口

进口和出口装备,以多页运用为例,有几个需求自己装备的字段

  • entry:两个页面的进口,entry下途径对应的 key 值(main page2),是有用处的,在出口 output 中自界说输出途径时,能够经过 [name] 拿到这个 key 值,出口的途径就和多进口相关起来了。

  • **output.path:**打包后产品的输出途径。

  • output.filename:打包后产品的称号,经过 [name] 能够取到当时打包产品来自的进口 entry 称号,path 与 filename 终究组合成完好的打包产品输出途径。

  • output.publicPath

    • 这是很重要且不简单了解的装备,是由于它会影响多个当地,它被用作资源途径的处理,而资源包含打包后的 .js、.css,包含引进的图片、媒体、文件,而每种资源的处理办法是不同的,有些 webpack 内部处理,有些需求凭借一些 plugin 插件,所以资源途径的处理进程会有点紊乱。

    • 比方你将 publicPath 设置成 /dist/,那么打包后 html 中引进 js css 的途径就会以 /dist/ 肯定途径最初,但它并不一定会收效,由于你或许运用了 html-webpack-plugin插件来生成 html ,这个插件中相同有 publicPath 装备,就会覆盖掉默许 output.publicPath 的装备。

    • 总而言之,output.publicPath 是最初始的资源引进途径的装备,是否会收效,取决于你对项目内各种资源的打包办法和放置方位,还要看终究服务是怎样布置,一般咱们将静态资源布置在域名 / 目录能直接拜访的方位,所以一般装备为”/“(这种办法在本地直接翻开 html 文件是拜访不到的,需求你在本地起一个拜访服务,或许装备成”./“相对途径才行)

  • output.clean:表明每次输出前先清空下目录,很有用,代替曾经的clean-webpack-plugin插件。

// webpack.config.js
import path from 'path'
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const { NODE_ENV = 'development' } = process.env;
export default {
  entry: {
    main: path.resolve(__dirname, '../src/main/index.jsx'),
    page2: path.resolve(__dirname, '../src/page2/index.jsx'),
  },
  output: {
    path: path.resolve(__dirname, '../dist/'),
    filename: 'js/[name]/[name].[contenthash].js',
    publicPath: '/',
    clean: true
  }
}

Loader 装备

webpack Loader 的装备这么多年没什么太大的变化,在 react 项目中就更简洁了

  • js&jsxbabel-loader处理js和jsx,babel这一套也是很繁琐,后边有专门章节介绍

  • css:现在咱们一般会用一个 css 预处理东西加强开发体会,我这儿用了 less ,所以本次项目中按顺序css编译依次经过 less-loader编译 less,css-loader编译 css,终究经过style-loader注入到 html 的 中,我这儿加了个判断开发环境下直接注入 ,出产环境独自打包出来(出产环境的一项 css 分离优化,合作 mini-css-extract-plugin 插件运用)

  • **资源处理:**资源处理是需求留意的,webpack5 专门引进了 asset 模块,在这之前你或许运用file-loader url-loader raw-loader来处理资源。asset供给了四种类型彻底代替旧方案。

    我这儿直接用 type: ‘asset’ 最灵敏的类型来处理一切图片资源编译和途径引进问题,maxSize 装备表明小于 4kb 直接编译进代码里(一般以base64的办法),大于4kb,一致存放到 generator.filename 装备的途径,留意 filename 只装备了一部分途径,终究打包后在代码里引进的途径是要拼接在 output.publicPath 基础之上的,比方 output.publicPath 装备为 /dist/ ,终究代码引进的途径便是 <img src="" />

一个 React 项目最根本的 Loader 装备这三个就足够了,假如你是 vue 项目应还需求 vue 供给的 vue-loader由于 .vue 文件是独自的语法,需求先编译成 js 文件,而 React jsx 实质上仍是 js (只需求在 babel 中引进 @babel/preset-react 的预设用于 编译 jsx),并不需求专门的 Loader。

假如你是 html 项目,还能够运用html-loader来解析 html 内部从0彻底梳理,2024年webpack5最佳实践(附demo示例)标签内的图片途径编译问题,由于 js 内资源途径的编译,是依靠 ESM(import)之类的模块引进才干辨认的,无法直接辨认 src=”” 这种字符串的。

export default {
  module: {
    rules: [
      {
        // 资源类处理与途径
        test: /.(png|jpe?g|gif|svg)(?.*)?$/,
        type: 'asset',
        generator: {
          filename: 'images/[hash][ext][query]'
        },
        parser: {
          dataUrlCondition: {
            maxSize: 4 * 1024 // 4kb
          }
        }
      },
      {
        // js jsx babel编译,细节经过babel.config.js独自装备
        test: /.m?js|jsx$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader'
        },
      },
      {
        // css 编译
        test: /.css|less/,
        use: [
          NODE_ENV === 'development' ? 'style-loader' : MiniCssExtractPlugin.loader,
          'css-loader',
          'less-loader',
        ],
      },
    ],
  },
}

Plugin 装备

plugin 是 webpack 敞开生态的中心,官方和社区都有丰富的 plugin 资源,webpack 构建流程尽管很杂乱,网络上能看到各种插件,但许多最佳实践都现已被验证过了,现在来到了 webpack 的 v5 版别,许多插件功用都已集成到 webpack 中开箱即用,所以你需求重视一下,你是不是还在用过期的插件。

外部插件需求先 npm install,官方插件可直接经过 webpack.pluginName 调用

html-webpack-plugin 编译html

依然是最常用的插件之一,webpack 只能围绕着 js 做编译,一般情况下,运用 html-webpack-plugin 做 html 的编译是很有必要的,此次项目是个多页运用示例,所以 html-webpack-plugin 需求履行两次,装备如下:

其间 publicPath 表明打包后的 html 中引进 js css 的途径,假如不设置,将运用 output.publicPath 装备的资源途径,怎样设置取决于怎样布置,比方设置成 ”./“ 相对途径需求确保 .html 与引进资源在同一目录,设置成 ”/“ 需求在布置服务器根目录下能拜访到该资源。

export default {
	plugins: [
   new HtmlWebpackPlugin({
      template: path.resolve(__dirname, '../src/main/index.html'),
      filename: 'main.html',
      chunks: ['main'],
      publicPath: '/'
    }),
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, '../src/page2/index.html'),
      filename: 'page2.html',
      chunks: ['page2'],
      publicPath: '/'
    }),
	]
}

webpack.DefinePlugin 构建时替换代码变量

能够经过它在构建进程向代码中替换代码中的变量,能够替换任何类型的数据,在实际开发中或许会很有用,比方在开发和出产环境注入不同的数据。

留意:构建时的替换与运行时的代码没有关系,仅仅朴实的字符串替换,实质是在编译时强制更换了代码内容,替换后的内容会在运行时履行,请确保替换内容的百分百安全可靠,并留意替换后的代码不会在运行时呈现语法错误

export default {
  plugins: [
    // 代码中一切 _WEBPACK_MODE_ 字符都将被替换成 JSON.stringify('development')
    new webpack.DefinePlugin({
      _WEBPACK_MODE_: JSON.stringify('development'),
    })
  ]
}

webpack.ProgressPlugin 构建进展

webpack 自己供给了构建进展的插件,能够在回调中拿到构建进展,输出控制台提示,便于观察。

我试了下发现这个插件有两个小问题,它在回调中返回的进展,总是从0.03开端,并进展1会履行两次(或许他的进展有更细的划分),这使我每次编译成功都会打印两遍,不知道为什么。

留意:ProgressPlugin 属于增强构建体会,关于编译进程没有任何协助,并且会添加编译时刻,可依据需求决议是否引进

// build/webpack.common.js
let progressStartTime = 0
export default {
  plugin: [
    new webpack.ProgressPlugin({
      handler(percentage, message, ...args) {
        // dev-server每次进展从0.03开端,不知道为啥
        if (percentage <= 0.03) {
          progressStartTime = Date.now();
        }else if (percentage > 0.03 && percentage < 1){
          console.log(`进展:${(percentage * 100).toFixed(0) + '% '}${message}${args.join(' ')}`)
        }else if (percentage === 1) {
          const cost = Date.now() - progressStartTime;
          process.stdout.write('n');
          vconsole.log(`编译完结,耗时:${cost}ms`);
        }
      },
    })
  ]
}

mini-css-extract-plugin 提取css到独自文件

上面说能够经过style-loader将打包后的 css 刺进到中,在出产环境下,为了优化体会拆分 css 到独自文件是十分有必要的,便于浏览器缓存,需求合作 MiniCssExtractPlugin.loader 运用。

留意:在 webpack 曾经的版别,或许经过 extract-text-webpack-plugin做类似作业,该方案已被抛弃

// build/webpack.prod.ja
export default {
  plugins:[
    new MiniCssExtractPlugin({
      filename: 'css/[name]/[name].css',
      chunkFilename: 'css/[name]/[id].css',
    })
  ]
}

SplitChunksPlugin 编译分块(内部集成)

分块是 webpack 很重要的一项优化办法,它会在多种情况下挑选将一部分代码拆出成一个独自的js文件:

  • 新的 chunk 能够被共享,或许模块来自于 node_modules 文件夹
  • 新的 chunk 体积大于 20kb(在进行 min+gz 之前的体积)
  • 当按需加载 chunks 时,并行恳求的最大数量小于或等于 30
  • 当加载初始化页面时,并发恳求的最大数量小于或等于 30

拆分后能够有效减小构建产品体积与增强浏览器缓存,该插件内部集成,运用时只需求经过 optimization.splitChunks 直接装备即可

留意:webpack 默许装备现已符合 web 性能最佳实践,当你确认真的需求时再去更改,一般情况你无需更改装备。

// build/webpack.prod.js
module.exports = {
  optimization: {
    splitChunks: {
      chunks: 'async',
      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,
        },
      },
    },
  },
};

webpack.HotModuleReplacementPlugin 热更新HMR(内部集成)

devServer 下的模块热替换,现已在 webpack-dev-server 内部集成,一般无需运用。

terser-webpack-plugin 紧缩编译(内部集成)

webpack5 内部集成了该插件,并会在出产环境下主动紧缩代码,一般情况下这是比较好的紧缩方案,无需更改。

留意:webpack5 无需装置、引进、装备该插件,假如你想自界说一些紧缩装备,则需求 “npm install terser-webpack-plugin –save-dev`装置后再装备

copy-webpack-plugin 仿制目录

能够在构建完毕后将某些文件直接仿制到构建后的目录中

留意:仿制进程不参与编译流程

Babel 编译

在 webpack 真正编译的环节,最首要的便是 js 编译,webpack 一般运用 Babel 做编译(你也能够挑选其他编译器比方最近因 vite 比较火的 esbuild),假如你能接受 Babel 的编译速度的话,主张仍是用 Babel ,实践案例最为丰富。

Babel 的编译比较杂乱,并且需求用到许多相关的包,主张将相关装备独自封装到babel.config.js,而不是写在 webpack 或许写在 package.json 里。

这又是一堆很糟心的装备,我都不知道要怎样讲清楚这玩意,能够专门出一篇文章,网上充斥各种紊乱过期的文章,提示一下假如你在网上查找相关文章,假如里边提到的任何包不是 @babel 最初,那这篇文章就不要看了,肯定过期了

留意:Babel 现在最新 v7 版别,发版到现在有许多抛弃的包,最新的 babel 包悉数是以 @babel 最初,不要再用旧的包了。

@babel/core

  • babel 中心功用,必引进

@babel/preset-env

  • Babel 最重要的有两个机制预设presets插件plugins,而预设便是一组插件的调集,由于在出产环境咱们需求依据不同的浏览器,来决议引进不同的插件(提升性能),所以官方推出了一个智能的presets@babel/preset-env,这是一大堆插件的调集,详细需求引进哪些,在运行时依据浏览器做最优的决议。

@babel/preset-react

  • 本次项目运用了 React,尽管 jsx 实质上是 js ,可是仍有很大不同,所以需求引进@babel/preset-react编译jsx 文件

@babel/plugin-transform-runtime 与 @babel/runtime-corejs3

要点来了,最简单让人迷惑的包,官方推出了两个 runtime 插件,首要为了处理两个问题

  1. 打包后每个文件最初都会引进补充文件,用于处理当时文件的兼容问题,比方某个浏览器不支持 js 某个办法或许压根缺少某个数据类型,就需求先声明这个办法或许引进相关的垫片(polyfill),每个打包后的文件都会引进当时文件缺失的部分,会有许多重复引进。
  2. 垫片(polyfill)的引进会形成全局污染,在事务项目中还好,假如是开发一些类库这个问题就严重了。

所以为了处理上述问题,就有了这两个包,@babel/plugin-transform-runtime装置在开发依靠项(devDependencies),“@babel/runtime-corejs3`需求在运行时运用所以要装置在出产依靠项(dependencies),@babel/runtime 有多个版别你能够了解为对应不同程度的语法兼容,corejs-3兼容的语法最多,所以咱们挑选corejs-3

从0彻底整理,2024年webpack5最佳实践(附demo示例)

所以咱们终究决议引进这5个包,编译成果根本兼顾性能与全面,可满意大都场景,详细装备如下:

// babel.config.js
export default {
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "browsers": ["last 2 versions", "not ie <= 10"]
        }
      }
    ],
    '@babel/preset-react'
  ],
  "plugins": [
    [
      "@babel/plugin-transform-runtime",
      {
        "corejs": 3,
      }
    ]
  ]
}

还有一个值得说一下便是@babel/preset-stage-?这个包在之前也常常被用到,常常装备"presets": ["stage-0"]用于在编译时能够挑选转义到 TC39 新语法的哪个阶段的提案,但在 babel v7 中被彻底抛弃了,详细可看 Removing Babel’s Stage Presets

Dev Server 开发服务器

Webpack 供给 Dev Server 功用,将 mode 设置为 ‘development’,有三种办法能够来构建敞开环境:

  1. webpack-dev-server,集成开箱即用的构建东西,会主动建立一个 devServer 服务,集成 HMR ,监听文件变化,无刷新热更新页面。
  2. 用 webpack 自带的 watch 和 watchOptions 装备项去监听,就仅仅简略的监听文件变化,然后重新走 build ,再手动刷新页面
  3. webpack-dev-middleware中间件,这个需求你自己建立 devServer 服务器。webpack-dev-server事务基于它完结的

一般情况下,在正常代码构建中,咱们会选用webpack-dev-server来构建开发环境,这是最适宜的挑选。

你能够向 Dev Server 添加一些常用装备,绝大大都装备运用默许即可

  • open:Dev Server 发动后会主动翻开浏览器,并可设置要翻开的路由

  • port:设置翻开的端口,默许 auto 会主动翻开一个搁置端口

  • hot:热更新,默许敞开

  • host:设置’0.0.0.0’,能够让之外的服务器拜访你的 dev server,否则是只允许你本地拜访的

  • proxy:是咱们最常用的设置,用于设置 Dev Server 的恳求代理,许多时分咱们打包后的前端代码会随着服务端代码一同布置到服务器上,所以咱们常常在前端代码中直接经过恳求当时服务器的 /api/add接口路由来恳求数据,咱们在本地开发时不或许每次把服务器代码也在本地发动,所以咱们能够经过 Dev Server 将当时的恳求,代理到一台布置了服务端代码的服务器上

    如下示例,咱们在前端代码直接恳求/api/add接口,会主动代理到http://api.test.com/api/add,咱们能够代理到服务端的测验环境完结联调,亦或许直接代理到线上服务,免除本地建立服务端环境。

// build/webpack.dev.com
export default {
  devServer: {
    open: ['/main.html'],
    port: 'auto',
    host: '0.0.0.0',
    hot: true,
    proxy: {
      '/api': 'http://api.test.com',
    },
  },
}

Dev Server 构建的产品并不会直接输出到文件中,只会保存到内存里,是看不到的,由于咱们一般无需运用开发环境的构建产品,也削减了磁盘写入的时刻,提升响应速度。

留意:其实 Dev Server 构建的开发环境和终究出产环境的构建产品是有巨大差异的,咱们能够看到这两者所构建的进程,运用的东西都有很大不同,原则上这是有很大风险的,不过 webpack 很好的兼容了这一点,并且历经时刻的验证,但作为一个项目的技能担任人,在引进一些新的构建东西时,咱们应该更加重视这一点。

从构建流程上,webpack 开发出产两种环境的构建原理最少是一致的,而像近几年比较火的vite更为极端,在开发和出产环境的构建的原理、编译流程都彻底不同,乃至编译 js 都是别离用 babel 和 esbuild 两种编译器,注定构建产品的差异更加大,这也是在考虑挑选构建东西时不行忽视的要素。

资源途径引进问题

独自拿一节来说下资源途径问题是由于这个问题关于不太了解 webpack 的人来说确实很简单遇到,归根到底其实 webpack 仅仅一个 js 打包的东西,至于打包出来的各种资源要怎样引证,webpack 并不太关怀,装备不清楚简单呈现 404 的情况。

【资源】的界说便是指 js 代码之外,需求独自引进的部分,包含 css、js、图片、视频等

html中的 js css 途径引进

  • output.publicPath 界说了最初的资源引进途径,一般将它设置成”/“即可,这是由于一般咱们会将前端代码布置到服务器恳求的根目录上(并不一定是服务器的根目录,一般被 nginx 或服务端转发),便是说咱们一般拜访www.test.com/js/main.js就能够拿到这个js文件,此刻在 html 中 script 引进途径便是 /js/main.js,这个途径是这台服务器的根目录,html 文件你能够放在任何方位。

    可是你设置成”/“在本地翻开 html 文件肯定是 404 的,由于你本地电脑没有服务端的这些环境和转发逻辑,这个肯定途径在你电脑上是拿不到 js 文件的,这种需求和服务端一同布置才是完好的逻辑。

  • 你也能够将 output.publicPath 设置为 ”./“ ,此刻在 html 中引进的便是 ./js/main.js相对途径,那此刻你在本地翻开 html 是能够拜访到这个 js 文件的,它既然是相对途径,那就要求布置时,html 与 js 在同一目录下。

  • 所以无论你怎样装备,你应该要了解终究的打包产品要怎样与服务端合作布置到服务器上。

图片等媒体资源途径引进

  • 图片资源的打包也一样,webpack 编译时能够将引进的图片一致存放到某个文件夹下,引进的途径仍是需求你来装备,假如依然运用 output.publicPath 的装备,假如你装备的是相对途径那代码和图片就需求确保相对方位是对的,这种情况设置成 ”/“ 肯定途径是最便利不易出错的,所以一般情况 output.publicPath 最好设置成肯定途径。

一共用到了多少个包

在整理了构建所需求用到的根本装备后,咱们数一下一共用到了多少个 npm 包,这简直现已是咱们构建一个标准项目用到最少包的极限了,除去 react 两个包,纯构建用到了 16 个 npm 包,这仍是在 webpack5 现已内置了许多常用功用的基础上。

所以说项目构建确实是一件十分繁琐的事。

// package.json 
{
  "devDependencies": {
    "@babel/core": "^7.23.5",
    "@babel/plugin-transform-runtime": "^7.23.4",
    "@babel/preset-env": "^7.23.5",
    "@babel/preset-react": "^7.23.3",
    "babel-loader": "^9.1.3",
    "cross-env": "^7.0.3",
    "css-loader": "^6.8.1",
    "html-loader": "^4.2.0",
    "html-webpack-plugin": "^5.5.3",
    "less-loader": "^11.1.3",
    "mini-css-extract-plugin": "^2.7.6",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "style-loader": "^3.3.3",
    "webpack": "^5.89.0",
    "webpack-dev-server": "^4.15.1",
    "webpack-merge": "^5.10.0"
  },
  "dependencies": {
    "@babel/runtime-corejs3": "^7.23.6"
  }
}

总结

  • 关于为什么要写一篇 webpack5 的装备实践呢,webpack 开展至今,阅历了许多阶段,有过各种最佳实践不停地从呈现到抛弃,网络上有很多的 webpack 相关技能文章,但大多都过期或许语焉不详,webpack 本身不是特别难,可是触及十分广的基础常识,操作系统、网络、编译、布置,所以我回想曾经在其间遇到的各种问题,结合最新的 webpack5 文档想写一篇更简单了解的最佳实践。

  • 编译是一个很专业的范畴,webpack 做了许多作业让杂乱的编译流程变的简略,但咱们应该清楚要担任一个项目的构建,你依然需求懂得整个编译流程的方方面面,这是在之后依据事务特色去优化出产代码,增强开发体会的条件。

  • 构建对一个项目来说常常是一写定终身,事务成熟之后咱们再去更改和优化构建的办法和战略,本钱和风险都会很大,所以咱们在项目之初做构建时仍是要慎重。

  • 想写一节关于 webpack 构建的优化战略,比较难,内容也会许多,还需求多调研下,所以下次再专门写一篇构建优化战略的文章。优化属于 webpack 的进阶运用了,实际上 webpack 默许的优化现已是十分到位了,肯定能够满意大大都项目的构建需求了。

  • 关于 webpack 的优化无非是构建进程、开发体会、构建产品三个方面,咱们一定要清楚程序质量一定是大于构建进程和开发体会的,不要为了削减构建时刻而影响构建产品的质量。

  • 文章触及内容较广,假如问题可在评论区指出,谢谢。

本文demo地址:webpack_demo

原创声明

原创文章,转载请注明作者和文章原链接 阿祖zu

参考文献