webpack5 多页面打包配置

webpack5 多页面打包配置

确定页面结构

1
2
3
4
5
6
├── package-lock.json
├── package.json
├── postcss.config.js
├── src 代码
├── tsconfig.json
└── webpack.config.js webpack配置文件
1
2
3
4
5
src
├── assets 静态资源
├── models ts 定义
├── pages 页面
└── scripts 一些工具函数
1
2
3
4
5
6
7
8
9
src/pages
├── course
│ ├── index.html
│ ├── index.ts
│ └── style.scss
├── course-intro
│ ├── index.html
│ ├── index.ts
│ └── style.scss

步骤

1. 安装 webpack

1
npm install webpack webpack-cli -D

配置package.json.

是为了后续打包配置判断环境需要的。 可以安装cross-env 替代

1
2
{"scripts": {    "build": "webpack --progress --mode=production", //
"dev": "webpack serve --mode=development", "build:analyze": "webpack --analyze --mode=production", },}

2. 配置多页面

配置入口文件

入口和上下文
| webpack 中文文档 (docschina.org)

我这里的代码会变成这样的形式, 自行自定义配置

1
2
{
'doctor/index': 'src/pages/doctor/index.ts'}
1
2
3
4
5
6
7
8
9
10
const srcPagePath = path.resolve(__dirname, 'src/pages');/** 获取所有页面文件夹 */function generatePages() {
const pageDirs = fs.readdirSync(srcPagePath, {
encoding: 'utf-8', }); return pageDirs;}
const pages = generatePages();module.exports = (env, argv) => {
const mode = argv.mode; return {
 // 入口文件 entry: {
...pages.reduce(
(prev, page) => ({
...prev, [`${page}/index`]: path.resolve(__dirname, `src/pages/${page}/index.ts`), }), {}, ), }, }
}

配置Output, 也是自定义的。 默认应当是dist文件夹

1
2
// 编译后放置的文件夹output: {
path: path.resolve(__dirname, 'dist'),},

3. html 页面配置

template 是要渲染的html,

filename 是打包出来的文件名

chunks 是上面entry的键。

1
2
3
4
const HtmlWebpackPlugin = require('html-webpack-plugin');plugins: [
// html 文件 ...pages.map((page) => {
return new HtmlWebpackPlugin({
template: path.resolve(__dirname, `src/pages/${page}/index.html`), filename: `${page}/index.html`, chunks: [`${page}/index`], }); }), ],

这样基本上就可以运行了。

可选

ts文件配置

为了可以编写ts文件。 需要安装 typescript
ts-loader

ts-loader 是为了让webpack识别ts文件。 但是ts-loader
会进行类型检查。 速度会比较慢, 这里用 babel-loader
配置.然后在提交git前执行 tsc --noEmit 检查类型。
为了自动化的话可以用git的pre-commit 自动执行检查

1
2
3
4
5
6
module: {
rules: [
// ts 文件处理 {
test: /\.ts$/, use: [
{
loader: 'babel-loader', }, // { // loader: 'ts-loader', // 先执行 // }, ], exclude: '/node-modules/', },]}

scss 文件处理

MiniCssExtractPlugin 和 style-loader 会冲突。 看个人选择

1
2
3
const MiniCssExtractPlugin = require('mini-css-extract-plugin');{
test: /\.(sc|c)ss$/, exclude: /node_modules/, use: [
MiniCssExtractPlugin.loader, // 'style-loader', 'css-loader', 'postcss-loader', 'sass-loader', ],},

图片处理

webpack5 自带静态文件处理loader。配置一下就行

1
2
3
{
test: /\.(png|jpg|gif|jpeg|webp|svg|eot|ttf|woff|woff2)$/, type: 'asset', generator: {
filename: 'static/[hash][ext][query]', },},

html 里面的图片如何处理

html-webpack-plugin 支持ejs 语法, 可以通过require处理

1
<img src="<%= require('./phone.png')%>" alt="">

或者通过js进行引入

1
const picEl = require('../xx.png)document.querySelector('img').src = picEl

或者当背景图用

1
background: url('@/assets/images/phone.png');

eslint

这个没有什么好说的, 搜eslint相关教程

babel 配置

如果需要coreJs,可以配置corejs。 babel 还需要browsetlist
文件进行辅助来按需引入

1
{    "presets": [        "@babel/preset-typescript",        "@babel/preset-env",        // ["@babel/preset-env", {        //     "useBuiltIns": "usage",        //     "corejs": {        //         "version": 3        //     }        // }]    ]}

完整配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/* eslint-disable @typescript-eslint/no-var-requires *//* eslint-disable import/no-extraneous-dependencies */const path = require('path');const fs = require('fs');const HtmlWebpackPlugin = require('html-webpack-plugin');const { CleanWebpackPlugin } = require('clean-webpack-plugin');const MiniCssExtractPlugin = require('mini-css-extract-plugin');const srcPagePath = path.resolve(__dirname, 'src/pages');/** 获取所有页面文件夹 */function generatePages() {
const pageDirs = fs.readdirSync(srcPagePath, {
encoding: 'utf-8', }); return pageDirs;}
const pages = generatePages();module.exports = (env, argv) => {
const mode = argv.mode; return {
mode: mode, // devtool: 'eval-cheap-module-source-map', devtool: mode === 'production' ? false : 'eval-cheap-module-source-map', // source-map // 入口文件 entry: {
...pages.reduce(
(prev, page) => ({
...prev, [`${page}/index`]: path.resolve(__dirname, `src/pages/${page}/index.ts`), }), {}, ), }, // 编译后放置的文件夹 output: {
path: path.resolve(__dirname, 'dist'), }, module: {
rules: [
// 静态文件处理 {
test: /\.(png|jpg|gif|jpeg|webp|svg|eot|ttf|woff|woff2)$/, type: 'asset', generator: {
filename: 'static/[hash][ext][query]', }, }, // { // test: /\.html$/, // use: ['html-loader'] // }, // ts 文件处理 {
test: /\.ts$/, use: [
{
loader: 'babel-loader', }, // { // loader: 'ts-loader', // 先执行 // }, ], exclude: '/node-modules/', }, {
test: /\.(sc|c)ss$/, exclude: /node_modules/, use: [
MiniCssExtractPlugin.loader, // 'style-loader', 'css-loader', 'postcss-loader', 'sass-loader', ], }, ], }, resolve: {
alias: {
'@': path.resolve('src'), }, // import 的时候可以不写 ts 后缀名 extensions: ['.ts', '.js'], }, plugins: [
// html 文件 ...pages.map((page) => {
return new HtmlWebpackPlugin({
template: path.resolve(__dirname, `src/pages/${page}/index.html`), filename: `${page}/index.html`, chunks: [`${page}/index`], }); }), new MiniCssExtractPlugin(), new CleanWebpackPlugin(), ], // 开发服务器配置 devServer: {
port: 3010, hot: true, proxy: {
'/api': {
target: 'https://xxxx.com', changeOrigin: true, }
}, }
};};