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…...

飞思实验室与中飞院联合开发教学课程,校企联袂共绘教育蓝图
近日,飞思实验室与中国民用航空飞行学院(以下简称“中飞院”) 航空电子电气学院合作,共同开发《无人智能视觉导航控制技术》、《多旋翼无人飞行器集群系统》实验课程。这一举措旨在深化校企融合,学校通过引入企业带来的…...

Telephony Call
1、Telephony 架构 Telephony整体架构和Android架构一样的,包括APP层,框架层,HAL层,内核层。 其中HAL层不同平台实现方式不同,其中MTK SPRD 平台使用AT通道的方式实现,高通使用QMI方式实现。 2、通话业务介绍 APP包括Dialer.apk、TeleService.apk、Tele…...

Python--TCP/UDP通信
文章目录 前言一、pandas是什么?二、使用步骤 1.引入库2.读入数据总结 一.客户端与服务端通信原理 1. 服务器端 服务器端的主要任务是监听来自客户端的连接请求,并与之建立连接,然后接收和发送数据。 创建套接字:首先࿰…...

【已解决】请教 “Sa-Token 集成 xxl-job,报错:非 web 上下文无法获取 HttpServletRequest” 如何解决
1. xxl-job 报错日志 2024-09-11 17:19:04 [com.xxl.job.core.thread.JobThread#run]-[133]-[xxl-job, JobThread-3-1726046344528] <br>----------- xxl-job job execute start -----------<br>----------- Param: 2024-09-11 17:19:04 [com.xxl.job.core.thread…...

Redis——常用数据类型string
目录 常用数据结构(类型)Redis单线程模型Reids为啥效率这么高?速度这么快?(参照于其他数据库) stringsetgetMSET 和 MGETSETNX,SETEX,PSETEXincr,incrby,decr…...

架构设计:负责网络、定时、坐下、站起、重连等,支持多类游戏的无锁房间
本文首发在这里 重中之重就是想实现无锁!无锁!无锁! 源码 servergolang 预计还会实现gate_server,接受并保持websocket长连接,按需双向流到game_server进行消息转发 未来上述服务均会以容器的形式由k8s自动化部署、…...

个人随想-gpt-o1大模型中推理链的一个落地实现
首先祝大家中秋节快乐。 最近openai又推出了新的模型openai o1还有它的mini版。官网的介绍,就是它的推理能力很强,比gpt-4o有很大的提升。 最近也跟同行在聊这个o1,看看落地方面有哪些可行性。在我们自己的实验上,把o1用…...

python解析ip范围,判断ip是否在ip范围内
目录 1. 背景 2. 代码使用示例 2.1 分割ip,横杠 (-) 的ip范围 2.2 判断ip在掩码(/)的范围内 2.3 判断ip在横杠(-)的范围内 2.3.1 格式:192.168.1.1-192.168.1.10 2.3.2 格式&…...

Springboot错误日志切面,找到post请求体被消费后的数据
问题记录:测试环境接口报错,日志里没有请求参数等信息,于是写了一个切面,但切面中获取不到 request的请求体,因为 post 请求体只能被消费一次,于是找解决办法 解决方法 既然 request 被消费了导致对应的请…...

【二十】【QT开发应用】listwidget右键菜单和删除item
创建项目,添加资源文件 在项目文件夹中创建resources资源文件夹。 在vs中打开qrc文件,选择添加资源文件。 选择我们resources资源文件中的所有文件作为资源文件。 最后不要忘记点击保存。 向ListWidget控件添加item 右键菜单 在.h文件中添加QMenu头…...

LabVIEW机动车动态制动性能校准系统
机动车动态制动性能测试系统通过高精度的硬件设备与LabVIEW软件的紧密配合,实现了对机动车制动性能的精确校准与评估。系统不仅提高了测试的精确性和效率,而且具备良好的用户交互界面,使得操作更加简便、直观。 项目背景 随着机动车辆数量的…...