webpack5 构建优化方案看这篇就够了!【Node.js进阶】
无论在面试还是内部晋升,webpack 构建优化方案 一直都是非常重要的部分。
webpack5构建加持
- 一、项目完成目标
- 二、搭建项目
- 1. 安装koa、@koa/router (如果已经配置可路过)
- 2. 创建入口文件
- 3. 安装构建依赖
- 4. 在项目根目录添加 `.babelrc` 文件
- 5. 添加测试接口
- 6. 启动服务
- 7. 请求接口进行测试
- 三、配置 webpack
- 1. 核心概念
- 2. 在项目根目录创建 webpack.config.js 文件
- 3. 测试构建
- 4. 优化构建配置
- 四、路由自动注册
- 1. 使用 require-directory
- 2. 使用 require.context(webpack)功能
- 五、配置别名
- 1. 使用 webpack 的别名功能
- 2. 使用 module-alias
一、项目完成目标
- 支持 es6+语法
- 开发热更新
- webpack5 构建
- 接口搭建
- 路由合并,路由自动注册
- 添加项目规范
- 配置自定义别名
二、搭建项目
# 创建项目目录
mkdir webpack5-node# 进入webpack5-node文件夹
cd webpack5-node# 初始化package.json
npm init -y# 创建源码目录
mkdir src
1. 安装koa、@koa/router (如果已经配置可路过)
yarn add koa @koa/router
2. 创建入口文件
touch src/app.js
3. 安装构建依赖
yarn add -D webpack webpack-cli @babel/node @babel/core @babel/preset-env babel-loader clean-webpack-plugin nodemon webpack-node-externals webpack-merge rimraf
4. 在项目根目录添加 .babelrc 文件
// .babelrc
{"presets": [["@babel/preset-env",{"targets": {"node": "current"}}]]
}
5. 添加测试接口
在 app.js 中添加测试接口,由于已经配置了 babel 解析,所以可以直接在 app.js 中写 es6+语法
// app.js
import Koa from 'koa'
import Router from '@koa/router'const app = new Koa()
const router = new Router()router.get('/', async ctx => {ctx.body = {status: 200,message: 'success',data: {nickname: 'Simon',title: '前端工程师',content: 'webpack5构建node应用'}}
})app.use(router.routes()).use(router.allowedMethods())const port = 3000
app.listen(port, () => console.log(`服务启动在 ${port} 端口`))
6. 启动服务
npx babel-node src/app.js
7. 请求接口进行测试

三、配置 webpack
中文文档
1. 核心概念
entry:入口;指示webpack应该使用哪个模块,默认值是./src/index.js;output:输出;output属性告诉webpack在哪里输出它所创建的bundle,默认值是./dist/main.js;loader:loader负责完成项目中各种各样资源模块的加载;plugins:插件;用来解决项目中除了资源模块打包以外的其他自动化工作。包括:打包优化,资源管理,注入环境变量;mode:模式;通过选择development,production或none之中的一个,来设置mode参数,你可以启用webpack内置在相应环境下的优化。其默认值为production;
2. 在项目根目录创建 webpack.config.js 文件
// webpack.config.js
const { DefinePlugin } = require('webpack')
const nodeExternals = require('webpack-node-externals')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')module.exports = {// 打包编译为某一端侧的可使用代码 默认值:web https://webpack.docschina.org/configuration/target/target: 'node',// 打包模式,可选择值:development、productionmode: 'development',// 控制是否生成,以及如何生成 source map。 https://webpack.docschina.org/configuration/devtool/#rootdevtool: 'eval-cheap-source-map',// 打包模块入口文件entry: {server: `${process.cwd()}/src/app.js`},// 打包后的输入文件output: {filename: '[name].bundle.js',path: `${process.cwd()}/dist`},// 匹配解析规则module: {rules: [{test: /\.(js|jsx)$/,use: {loader: 'babel-loader'},exclude: [`${process.cwd()}/node_modules`]}]},// 构建过程中使用的插件plugins: [new CleanWebpackPlugin(),new DefinePlugin({'process.env': {NODE_ENV: JSON.stringify(process.env.NODE_ENV === 'production' ||process.env.NODE_ENV === 'prod'? 'production': 'development')}})],// 防止第三方依赖被打包externals: [nodeExternals()]
}
3. 测试构建
npx webpack

构建成功!
🤔❓
在实际开发中可能会存在开发环境和生产环境的构建,所以单凭一个配置还不能达到实际的需求,接下来对开发环境和生产环境分别配置。
在项目根目录创建 config 文件,并创建三个文件分别是:
webpack.config.base.js文件存放开发环境和生产环境都是需要的构建配置webpack.config.dev.js文件存放开发环境的构建配置webpack.config.prod.js存放生产环境的构建配置
4. 优化构建配置
mode独立于构建环境,开发环境为(development)、生产环境为(production)devtool只有在开发环境下才会存在stats属性让你更精确地控制打包后的信息该怎么显示 【Stats 对象】
Tips 🤔
由于每个开发环境和生产环境都是独立的构建配置,所以要在构建时要合并基础配置;
安装webpack-merge合并构建配置
npm i -D webpack-merge
-
优化基础构建配置
webpack.config.base.js// config/webpack.config.base.js const { DefinePlugin } = require('webpack') const nodeExternals = require('webpack-node-externals') const { CleanWebpackPlugin } = require('clean-webpack-plugin')module.exports = {// 打包编译为某一端侧的可使用代码 默认值:web https://webpack.docschina.org/configuration/target/target: 'node',// 打包模式,可选择值:development、production// mode: "development",// 控制是否生成,以及如何生成 source map。 https://webpack.docschina.org/configuration/devtool/#root// devtool: "eval-cheap-source-map",// 打包模块入口文件entry: {server: `${process.cwd()}/src/app.js`},// 打包后的输入文件output: {filename: '[name].bundle.js',path: `${process.cwd()}/dist`},// 匹配解析规则module: {rules: [{test: /\.(js|jsx)$/,use: {loader: 'babel-loader'},exclude: [`${process.cwd()}/node_modules`]}]},// 构建过程中使用的插件plugins: [new CleanWebpackPlugin(),new DefinePlugin({'process.env': {// 设置环境变量 NODE_ENVNODE_ENV: JSON.stringify(process.env.NODE_ENV === 'production' ||process.env.NODE_ENV === 'prod'? 'production': 'development')}})],// 防止第三方依赖被打包externals: [nodeExternals()] } -
开发环境的构建配置
webpack.config.dev.js// config/webpack.config.dev.js const { merge } = require('webpack-merge') const baseWebpackConfig = require('./webpack.config.base')const webpackConfig = merge(baseWebpackConfig, {devtool: 'eval-cheap-source-map',mode: 'development',// 是否添加关于子模块的信息。stats: { children: false } })module.exports = webpackConfig -
生产环境的构建配置
webpack.config.prod.js生产环境构建时要进行代码压缩,需要安装
terser-webpack-plugin
命令:npm i -D terser-webpack-plugin// config/webpack.config.prod.js const { merge } = require('webpack-merge') const TersetWebpackPlugin = require('terser-webpack-plugin') const baseWebpackConfig = require('./webpack.config.base')const webpackConfig = merge(baseWebpackConfig, {devtool: 'eval-cheap-source-map',mode: 'production',stats: { children: false },// 优化配置optimization: {// 压缩配置minimize: true,minimizer: [new TersetWebpackPlugin()],// 分块策略splitChunks: {// 缓存组 https://webpack.docschina.org/plugins/split-chunks-plugin/#splitchunkscachegroupscacheGroups: {commens: {name: 'commons',chunks: 'initial',minChunks: 3,enforce: true}}}} })module.exports = webpackConfig -
添加构建脚本命令
-
设置环境变量
NODE_ENV,由于各环境配置的差异问题,cross-env可以有效的解决跨平台设置环境变量的问题; -
它是运行跨平台设置和使用环境变量(Node 中的环境变量)的脚本。
-
安装命令:
npm i -D cross-env安装成功后配置构建命令 -
在 package.json 的
scripts中添加如下命令:"build": "cross-env NODE_ENV=prod webpack --config config/webpack.config.prod.js", "dev": "cross-env NODE_ENV=dev nodemon --exec babel-node --inspect src/app.js",
-
-
启动开发环境服务
npm run dev- 运行之后的效果图如下

- 运行之后的效果图如下
-
启动编译构建命令
npm run build- 运行效果如下图:

- 查看 dist 文件夹下被编译后的文件:

代码被压缩成了一整行!
- 运行效果如下图:
四、路由自动注册
1. 使用 require-directory
在 src 文件夹下新建 routes 和 api 两文件夹;
routes 是集成当前项目的所有路由
api 文件是存放项目的所有接口文件
-
安装
require-directory,这个包的作用可以将一个目录下的所有模块来自动注册Koa应用的路由,从而避免手动导入和注册每个路由文件。npm i require-dirctory -
创建
src/api/v1下创建 demo.js 和 test.js 文件// src/api/v1/demo.js import Router from '@koa/router'const router = new Router({ prefix: '/api/v1' })router.get('/demo', async ctx => {ctx.body = {status: 200,message: 'message',data: {file: 'demo.js',title: 'webpack 5 构建node应用',content: 'koa + @koa/router + require-dirctory'}} })export default router// src/api/v1/test.js import Router from '@koa/router'const router = new Router({ prefix: '/api/v1' })router.get('/test', async ctx => {ctx.body = {status: 200,message: 'message',data: {file: 'test.js',title: 'webpack 5 构建node应用',content: 'koa + @koa/router + require-dirctory'}} })export default router -
配置
src/routes/index.js// src/routes/index.js import Router from '@koa/router' import requireDirectory from 'require-directory'// 接口存放目录路径 const apiDirectory = `${process.cwd()}/src/api`function initLoadRoutes(app) {requireDirectory(module, apiDirectory, {visit({ default: router }) {if (router instanceof Router) {app.use(router.routes())}}}) }export default initLoadRoutes -
修改
src/app.js文件// src/app.js import Koa from 'koa' import initLoadRoutes from './routes/index'const app = new Koa()// 在入口文件中执行 initLoadRoutes(app)const port = 3002 app.listen(port, () => console.log(`服务启动在${port}端口`)) -
测试请求
🎉 至此,自动注册路由就大功告成了,后面我们定义接口的时候就用手动一个一个的引入,只管往 api 文件夹里写接口就好了。
2. 使用 require.context(webpack)功能
require 依赖管理
eg.:
.
├── modules
│ ├── adminRouter.js
│ ├── commentsRouter.js
│ ├── contentRouter.js
│ ├── loginRouter.js
│ ├── publicRouter.js
│ ├── userRouter.js
│ └── wxRouter.js
└── routes.js
目标:使用 routes.js 来动态加载 modules 目录中的 .js 的路由文件,其他的比如:vuex、vue-router 等场景,都适合。
上代码
// routes.jsimport combineRoutes from 'koa-combine-routers'// 加载目录中的Router中间件
const moduleFiles = require.context('./modules', true, /\.js$/)// reduce方法去拼接 koa-combine-router所需的数据结构 Object[]
const modules = moduleFiles.keys().reduce((items, path) => {const value = moduleFiles(path)items.push(value.default)return items
}, [])export default combineRoutes(modules)
使用方法
在 index.js 入口文件中:
import router from './routes/routes'app.use(router())
🧀🧀 两个小知识:
- 使用
koa-combine-routers可以合并多个路由- 使用
require.context可以动态引入多个文件
五、配置别名
在日常开发中我们引入一些封装好的方法或者模块总是写很长很长的文件路径;比如:
require('../../../../some/very/deep/module')
import format from '../../../../utils/format'
为了告别这种又臭又长的路径我们就可以使用一些解放生产力的方法了(哈哈哈哈,不会偷懒的程序员不是好程序员 🤭)
配置别名有两种方式,一种是 webpack,另一种是通过 module-alias 包
1. 使用 webpack 的别名功能
官方文档: resolve.alias
配置方式,非常的简单方便:
const path = require('path');module.exports = {//...resolve: {alias: {'@': path.resolve(__dirname, 'src/'),// ...},},
};
2. 使用 module-alias
-
安装依赖
npm i module-alias -
在
package.json中添加自定义别名"_moduleAliases": {"@": "./src","@controller": "./src/controller" } -
在入口文件的顶部引入
module-alias/register,也就是在 app.js 的顶部引入// src/app.js require('module-alias/register') ... -
配置成功后,将
/src/api/v1内的逻辑全部提到src/controller中,使用别名引入 controller 中文件,修改后如下:// src/api/v1/demo.js import Router from '@koa/router' import DemoController from '@controller/demo/'const router = new Router({ prefix: '/api/v1' })router.get('/demo', DemoController.demo)export default router// src/api/v1/test.js import Router from '@koa/router' import TestController from '@controller/test'const router = new Router({ prefix: '/api/v1' })router.get('/test', TestController.test)export default router// src/controller/v1/demo.js class DemoController {constructor() {}async demo(ctx) {ctx.body = {status: 200,message: 'message',data: {file: 'test.js',title: 'webpack 5 构建node应用',content: 'koa + @koa/router + require-dirctory'}}} }export default new DemoController()// src/controller/v1/test.js class TestController {constructor() {}async test(ctx) {ctx.body = {status: 200,message: 'message',data: {file: 'test.js',title: 'webpack 5 构建node应用',content: 'koa + @koa/router + require-dirctory'}}} }export default new TestController() -
测试接口
🙋 🙋
如果 git commit 时lint-staged没有通过:
上述问题是因为 eslint 发现 @controller/* 开头的在 node_modules 中没有找到,所以配置 eslint 就好了:
// src/eslintrc.js
module.exports = {//...rules: {'import/no-unresolved': [2, { ignore: ['^@/', '@controller'] }] // @和@controller 是设置的路径别名}
}

这个问题是由于
constructor构造函数为空引起的,在eslintrc.js添加配置即可:
'no-empty-function': ['error', { allow: ['constructors'] }]
希望上面的内容对你的工作学习有所帮助!欢迎各位一键三连哦~
各位 加油!
✨ 原创不易,还希望各位大佬支持一下 \textcolor{blue}{原创不易,还希望各位大佬支持一下} 原创不易,还希望各位大佬支持一下
👍 点赞,你的认可是我创作的动力! \textcolor{green}{点赞,你的认可是我创作的动力!} 点赞,你的认可是我创作的动力!
⭐️ 收藏,你的青睐是我努力的方向! \textcolor{green}{收藏,你的青睐是我努力的方向!} 收藏,你的青睐是我努力的方向!
✏️ 评论,你的意见是我进步的财富! \textcolor{green}{评论,你的意见是我进步的财富!} 评论,你的意见是我进步的财富!
相关文章:
webpack5 构建优化方案看这篇就够了!【Node.js进阶】
无论在面试还是内部晋升,webpack 构建优化方案 一直都是非常重要的部分。 webpack5构建加持 一、项目完成目标二、搭建项目1. 安装koa、koa/router (如果已经配置可路过)2. 创建入口文件3. 安装构建依赖4. 在项目根目录添加 .babelrc 文件5. …...
esp32-C2 对接火山引擎实现智能语音(一)
目录 一、火山引擎大模型简介 1)火山引擎网址: 2)首先需要先注册火山引擎账号 3)语音识别——即语音转为文本 一句话识别 流式语音识别 录音文件识别标准版 录音文件识别极速版 4)语音合成——文本转音频 一、火山引擎大模型简介 火山引擎的智能语音技术,基于业界先…...
【MySQL-初级】mysql基础操作(账户、数据库、表的增删查改)
概述 数据备份与恢复 数据库备份:在cmd下 root用户:sudo mysqldump -u root -p Test > Test.sql普通用户:mysqldump -u zzz -p db_name > db_name.sql 数据库恢复 先创建一个空的数据库在cmd下:sudo mysql -u root -p d…...
centos bash脚本一键运行安装go环境
复制到install_go.sh直接bash install_go.sh运行就完了 echo ----------安装go环境 wget https://go.dev/dl/go1.21.13.linux-amd64.tar.gz tar -zxvf go1.21.13.linux-amd64.tar.gzmkdir /srv cp -r go /srv/echo "PATH$PATH:/srv/go/bin ">> ~/.bashrc echo…...
vue2制作高复用页面
记录一下页面搭建记录,利用vue2组件化开发的思想。这个页面适合于大部分信息管理系统~。模板固定,每次使用,直接修改表单表格参数,api接口等。 以上图页面为例,一个基础数据信息页面可以分为,分类ÿ…...
Feed流系统重构:架构篇
重构对我而言,最大的乐趣在于解决问题。我曾参与一个C#彩票算奖系统的重构,那时系统常因超时引发用户投诉。接手任务时,我既激动又紧张,连续两天几乎废寝忘食地编码。结果令人振奋,算奖时间从一小时大幅缩短至十分钟。…...
Android 后台服务之Persistent 属性
在 Android 开发中,有时我们需要后台服务持续运行,以保持应用的某些功能。例如,音乐播放器需要在后台播放音乐,或者健康应用需要持续跟踪用户的运动数据。后台服务是 Android 中的一种组件,它不与用户界面交互,能够在后台执行长时间运行的任务。由于 Android 系统的资源管…...
STM32+ESP01连接到机智云
机智云,全球领先的智能硬件软件自助开发及物联网(iot)云服务平台。机智云平台为开发者提供了自助式智能硬件开发工具与开放的云端服务。通过傻瓜化的自助工具、完善的SDK与API服务能力最大限度降低了物联网硬件开发的技术门槛,降低开发者的研发成本,提升…...
电脑实时监控软件有哪些?七个电脑屏幕监控软件任你选择
电脑实时监控软件种类繁多,每款软件都有其独特的功能和适用场景。 以下是七个备受推荐的电脑屏幕监控软件,供您选择: 1.安企神: 功能:它是一款国内领先的企业级电脑监控解决方案, 提供实时屏幕监控、 文…...
信奥学习规划(CSP-J/S)
CSP-J组学习路线规划 CSP-S组学习规划...
【Linux取经之路】编译器gcc/g++的使用 调试器gdb的使用
目录 背景知识 编译器gcc/g的安装 编译器gcc/g的使用 调试器gdb的使用 cgdb 条件断点 背景知识 子曰:“温故而知新”。在谈gcc/g的使用之前,我们先来复习编译的4个阶段,也算是为下面的内容做一些铺垫,请看思维导图。 编译…...
自动化流程机器人(RPA)
自动化流程机器人(RPA)正逐渐成为企业提高效率和降低成本的强有力工具。 一、RPA的概念 自动化流程机器人(Robotic Process Automation,简称RPA)是一种利用软件机器人(Robot)模拟和执行复杂任务…...
Unity persistentDataPath使用案例
Unity persistentDataPath使用案例 一、Application.persistentDataPath 1、概念 persistentDataPath:此属性用于返回一个持久化数据存储目录的路径,可以在此路径下存储一些持久化的数据文件;是一个可读写的目录;此文件夹在Edi…...
Android 测试手册
1. 介绍 Android 测试是确保应用程序质量的重要步骤。它包括不同类型的测试,用于验证应用程序的功能、性能、安全性和用户体验。这个手册将指导你了解和实施 Android 测试的主要方法和工具。 2. 测试类型 2.1 单元测试 目的:验证单个组件(…...
各大平台统遭入侵??区块链市场遭攻击损失近3亿!
今年,全球发生多起骇人听闻的勒索入侵软件攻击事件,黑客组织利用各种手段和技术,不断试图突破网络安全防线,窃取敏感信息、破坏系统运行,甚至进行勒索和敲诈,使得网络安全问题日益凸显其重要性和紧迫性。 S…...
Java泛型(“代码模板”,一套代码套用各种类型)
1.什么是泛型 a.定义 i.如果不用泛型定义,在使用ArrayList时需要为每个class编写特定类型代码。 ii.泛型就是定义一种模板,既实现了编写一次,万能匹配,又通过编译器保证了类型安全。 iii.编写模板代码来适应任意…...
速响低代码平台:升级营销管理系统,开启高效无忧新体验!
当前日新月异的商业环境,企业面临着前所未有的挑战与机遇。随着市场竞争的日益加剧和企业业务的不断拓展,传统的营销方式和管理手段逐渐显露出其局限性,难以适应快速变化的市场需求。 数据收集难:传统的营销管理缺乏对客户数据的收…...
Gitlab升级14.0.12-->14.3.6遇到的gitlab-ctl reconfigure错误
问题描述 在按照官方文档升级路线11.0.2>17.2.2的过程中,升级14.0.12–》14.3.6时遇到一个错误: Running handlers: There was an error running gitlab-ctl reconfigure:rails_migration[gitlab-rails] (gitlab::database_migrations line 51) had…...
JDBC导图
思维歹徒 一、使用步骤 二、SQL注入 三、数据库查询(查询) 四、数据库写入(增删改) 五、Date日期对象处理 六、连接池使用 创建连接是从连接池拿,释放连接是放回连接池 七、事务和批次插入 八、Apache Commons DBUtil…...
飞思实验室与中飞院联合开发教学课程,校企联袂共绘教育蓝图
近日,飞思实验室与中国民用航空飞行学院(以下简称“中飞院”) 航空电子电气学院合作,共同开发《无人智能视觉导航控制技术》、《多旋翼无人飞行器集群系统》实验课程。这一举措旨在深化校企融合,学校通过引入企业带来的…...
Day131 | 灵神 | 回溯算法 | 子集型 子集
Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...
如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...
2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...
20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
在树莓派上添加音频输入设备的几种方法
在树莓派上添加音频输入设备可以通过以下步骤完成,具体方法取决于设备类型(如USB麦克风、3.5mm接口麦克风或HDMI音频输入)。以下是详细指南: 1. 连接音频输入设备 USB麦克风/声卡:直接插入树莓派的USB接口。3.5mm麦克…...
Neko虚拟浏览器远程协作方案:Docker+内网穿透技术部署实践
前言:本文将向开发者介绍一款创新性协作工具——Neko虚拟浏览器。在数字化协作场景中,跨地域的团队常需面对实时共享屏幕、协同编辑文档等需求。通过本指南,你将掌握在Ubuntu系统中使用容器化技术部署该工具的具体方案,并结合内网…...

