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. 请求接口进行测试

todo

三、配置 webpack

中文文档

1. 核心概念
  • entry:入口;指示 webpack 应该使用哪个模块,默认值是 ./src/index.js
  • output:输出;output 属性告诉 webpack 在哪里输出它所创建的 bundle,默认值是 ./dist/main.js
  • loaderloader 负责完成项目中各种各样资源模块的加载;
  • plugins:插件;用来解决项目中除了资源模块打包以外的其他自动化工作。包括:打包优化,资源管理,注入环境变量;
  • mode:模式;通过选择 development, productionnone 之中的一个,来设置 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.jsonscripts 中添加如下命令:

      "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
    
    • 运行之后的效果图如下todo
  • 启动编译构建命令

    npm run build
    
    • 运行效果如下图:
      在这里插入图片描述
    • 查看 dist 文件夹下被编译后的文件:
      在这里插入图片描述

    代码被压缩成了一整行!

四、路由自动注册

1. 使用 require-directory

src 文件夹下新建 routesapi 两文件夹;
routes 是集成当前项目的所有路由
api 文件是存放项目的所有接口文件

  • 安装 require-directory,这个包的作用可以将一个目录下的所有模块来自动注册Koa应用的路由,从而避免手动导入和注册每个路由文件。

    npm i require-dirctory
    
  • 创建 src/api/v1 下创建 demo.jstest.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 的路由文件,其他的比如:vuexvue-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())

🧀🧀 两个小知识:

  1. 使用 koa-combine-routers 可以合并多个路由
  2. 使用 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}{评论,你的意见是我进步的财富!} 评论,你的意见是我进步的财富!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/426365.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一般在写SQL时需要注意哪些问题,可以提高查询的效率?

很多人写SQL按照自己喜好,没有规则意识,这对于自主查询影响不大,你爱怎么搞就怎么搞,一旦涉及到提交任务或团队共享,就不能乱写了,会浪费资源影响到开发效率,严重的甚至会服务器瘫痪。 提几个关…

进程的重要函数

进程的重要函数: fork函数 了解fork函数 通过调用fork()函数&#xff0c;则会产生一个新的进程。调用fork()函数的进程叫做 父进程&#xff0c;产生的新进程则为子进程。 其编码过程: 1.函数功能: 函数头文件 #include <sys/types.h> #include <unistd.h> 函数…

运用Java实现倒计时功能

这个功能其实是比较好实现的&#xff0c;一般来说java中实现倒计时有两种方法&#xff1a; 1、使用 scheduledexecutorservice创建一个可重复执行的任务&#xff0c;直到时间到&#xff1a; ScheduledExecutorService 是 Java 中一种用于安排延迟或定期任务的工具。我们可以使…

云计算第四阶段------CLOUD Day4---Day6

Cloud DAY4 项目架构图&#xff1a; 环境准备&#xff1a; 主机名称IP地址配置logstash192.168.1.27最低配置4核8G #书接上文&#xff0c;我们在华为云平台租了几台云服务器&#xff0c;这次买一台性能好的服务器&#xff0c;作为logstash软件部署的载体。 今天给小伙伴们带来…

低代码门户技术:构建高效应用的全新方式

什么是低代码门户技术&#xff1f; 低代码门户技术是一种利用低代码平台构建企业门户网站或应用的技术。门户通常是企业内部和外部用户访问信息和应用的集中平台。低代码门户技术通过图形化界面和预置组件&#xff0c;允许用户快速搭建和定制这些门户平台&#xff0c;而无需深…

TCP并发服务器的实现

一请求一线程 问题 当客户端数量较多时&#xff0c;使用单独线程为每个客户端处理请求可能导致系统资源的消耗过大和性能瓶颈。 资源消耗&#xff1a; 线程创建和管理开销&#xff1a;每个线程都有其创建和销毁的开销&#xff0c;特别是在高并发环境中&#xff0c;这种开销…

性能测试的复习3-jmeter的断言、参数化、提取器

一、断言、参数化、提取器 需求&#xff1a; 提取查天气获取城市名请求的响应结果&#xff1a;城市对查天气获取城市名的响应结果进行响应断言和json断言对查天气获取城市名添加用户参数 1、步骤 查看天气获取城市名 json提取器&#xff08;对响应结果提取、另一个接口请求…

简单了解微服务--黑马(在更)

认识微服务 单体架构 不适合大型复杂项目 微服务架构 将单体结构的各个功能模块拆分为多个独立的项目 拆取的独立项目分别开发&#xff0c;在部署的时候也要分别去编译打包&#xff0c;分别去部署&#xff0c;不同的模块部署在不同的服务器上&#xff0c;对外提供不同的功能…

小间距LED显示屏的技术原理分析

在现代显示技术领域&#xff0c;小间距LED显示屏以其卓越的显示效果和灵活的应用场景&#xff0c;逐渐成为市场的新宠。本文将深入探讨小间距LED显示屏的技术原理&#xff0c;分析其在显示领域的应用优势。 A、小间距LED显示屏的基本概念 小间距LED显示屏是指LED灯珠之间的间距…

linux hadoop-3.3.6 hbase-2.5.7

软件下载 hadoop https://dlcdn.apache.org/hadoop/common/hadoop-3.3.6/hadoop-3.3.6.tar.gz 可以直接下载到本地&#xff0c;也可以直接下载进虚拟机中 如果速度较慢&#xff0c;可以用&#xff1b;另一个 wget https://mirrors.tuna.tsinghua.edu.cn/apache/hadoop/common…

spring-boot-maven-plugin插件打包和java -jar命令执行原理

文章目录 1. Maven生命周期2. jar包结构2.1 不可执jar包结构2.2 可执行jar包结构 3. spring-boot-maven-plugin插件打包4. 执行jar原理 1. Maven生命周期 Maven的生命周期有三种&#xff1a; clean&#xff1a;清除项目构建数据&#xff0c;较为简单&#xff0c;不深入探讨&a…

spring容器创建bean过程中使用到的几个factory

文章目录 前述BeanFactoryFactoryBeanObjectFactory 前述 spring我们可以理解为一个帮我们管理bean的容器&#xff0c;使用spring框架之前创建bean都是通过new的方式&#xff0c;使用spring框架之后&#xff0c; 我们只需要告诉spring框架我们有那些bean&#xff0c;它会帮我们…

k8s证书过期处理

证书一共分为 根CA&#xff08;ca.crt&#xff09; master各组件的证书&#xff08;包括etcd、apiserver、front-proxy、controller-manager等各种&#xff09; kubelet证书 k8s证书有效期说明&#xff1a; 1、原生版本有效期master节点&#xff1a; /etc/kubernetes/ssl/…

YOLOv10改进系列,YOLOv10损失函数更换为Powerful-IoU(2024年最新IOU),助力高效涨点

改进前训练结果: 改进后的结果: 摘要 边界框回归(BBR)是目标检测中的核心任务之一,BBR损失函数显著影响其性能。然而,观察到现有基于IoU的损失函数存在不合理的惩罚因子,导致回归过程中锚框扩展,并显著减缓收敛速度。为了解决这个问题,深入分析了锚框扩展的原因。针…

基于 K8S kubernetes 的常见日志收集方案

目录 1、日志对我们来说到底重不重要&#xff1f; 2、常见的日志收集方案 2.1 EFK 2.2 ELK Stack 2.3 ELKfilebeat 2.4 其他方案 2、elasticsearch组件介绍 3、filebeat组件介绍 3.1 filebeat和beat关系 3.2 filebeat是什么&#xff1f; 3.3 Filebeat工作原理 3.4 …

ELFK日志分析平台,架构和通信

整个架构&#xff0c;加上跳板机&#xff0c;总共12台机器 技术方案&#xff1a; 1. 配置nfs服务器&#xff0c;为web集群提供共享网络文件系统 # 部署 NFS 服务 [rootnfs ~]# dnf install -y nfs-utils [rootnfs ~]# vim /etc/exports /var/webroot 192.168.1.0/24(rw,…

xml重点笔记(尚学堂 3h)

XML:可扩展标记语言 主要内容(了解即可) 1.XML介绍 2.DTD 3.XSD 4.DOM解析 6.SAX解析 学习目标 一. XML介绍 1.简介 XML(Extensible Markup Language) 可扩展标记语言&#xff0c;严格区分大小写 2.XML和HTML XML是用来传输和存储数据的。 XML多用在框架的配置文件…

剖析 MySQL 数据库连接池(C++版)

目录 ☀️0. 前言 &#x1f324;️1. 数据库连接池概述 ⛅1.1 服务器与数据库交互 ⛅1.2 MySQL 数据库网络模型 ⛅1.3 MySQL 连接驱动安装 ⛅1.4 同步&#xff08;synchronous&#xff09;连接池与异步&#xff08;asynchronous&#xff09;连接池 ⛅1.5 同步连接池和异…

记录开发一个英语听力训练网站

背景 在当前全球经济衰退的背景下&#xff0c;IT相关的工作在国内的竞争也是越来越激烈&#xff0c;为了能够获得更多的可能性&#xff0c;英语的学习也许能为程序员打开一扇新的窗户&#xff0c;比如很多远程的工作尤其是国际化背景的工作团队&#xff0c;英语的协作沟通是必…

yolov8-obb中存在的一个bug

yolov8支持OBB目标检测,且能提供较好的性能。 但是最近在使用yolov8-obb的过程中,发现yolov8-obb存在一个bug。即训练数据如果包含不带旋转角度的水平目标时,训练出的模型,经常会输出垂直的检测框,需要旋转90度以后才能得到最终结果。把yolov8-obb相关的源码阅读一遍才发…