当前位置: 首页 > news >正文

前端工程化之新晋打包工具

新晋打包工具

  • 新晋打包工具
    • 前端模块工具的发展历程
    • 分类
    • 初版构建工具
      • grunt
        • 使用场景
      • gulp
        • 采用管道机制
        • 任务化配置与api简洁
    • 现代打包构建工具基石--webpack
    • 基于webpack改进的构建工具
      • rollup 推荐
        • 举例说明
          • package.json
          • rollup.config.mjs
          • my-extract-css-rollup-plugin.mjs
          • src/index.js
        • src/utils.js
          • src/index.css
        • src/utils.css
        • build/cjs.js
        • build/esm.js
        • build/umd.js
        • build/index.css
        • build/666.css
        • 使用场景
        • 不适用场景
      • Parcel 不推荐
        • 举例说明
          • parcel/index.html
          • parcel/index.js
          • parcel/App.js
          • parcel/index.css
          • package.json
        • 使用场景
    • 突破JS语言特性的构建工具
      • SWC 推荐使用 √ - 平替babel
        • jsc-parser语法解析相关配置
        • jsc-target 输出代码的es版本
        • 典型配置案例
      • ESbuild - 作为工具去使用的
    • 基于ES Module的bundleless(no bundle)构建工具 => vite
      • 基于bundle的解决方案
      • vite - 重点掌握
        • vite原理
        • 为什么vite之前没有,到2021年后才有这样的开发链路呢?
        • vite插件
          • package.json
          • vite.config.js
          • 自定义插件 -plugins/myPlugin.js
        • vite插件的相关钩子
        • 通用钩子
      • rspack - 推荐尝试使用
        • 示例:通过 rsbuild 创建一个工程
      • turpopack 国外的

新晋打包工具

构建为了将工程化的思想和自动化的思想应用在前端的工程链路中

前端模块工具的发展历程

  • 09年,commonJS:指定浏览器外js的相关 api 规范, nodejs 就采用了这样的规范
  • 11年,requireJS:作为客户端模块加载器,提供了异步加载模块的能力,之后就变成了 AMD 的规范
  • 13年,grunt,gulp 诞生。
  • 14年,UMD,统一模块定义,跨平台的前后端兼容
  • 14年,6to5,ES6 语法 => ES5,经历了 词法分析,语法分析,AST => new AST => generator code。这也就是 babel 的能力
  • 14年,system is 简化模块加载工具
  • 14年,webpack,第一个稳定版本的
  • 15年,ES6 规范正式发布的
  • 15年,rollup 基于ES6模块化,并且提供 tree shaking相关能力
  • 17年,Parcel,零配置,内部集成配置,能力进行收口,parcel,index.html
    => 做平台,开发基础能力,具备插件化机制
  • 19年,构建工具深水区,不再使用js语言卷了,使用go,rust语言来卷。由于JS是高级语言,使用 babel 会经历各种AST转换
    snowpack,使用rust语言,天生支持多线程能力
  • 20年,浏览器对 ESM,http2 支持,使得 bundless 思路开始出现,esbuild 进入到大众视野中
  • 21年,vite诞生

分类

  • 初版构建工具
  • 现代打包构建工具基石 webpack
  • 突破JS语言特性的构建工具
  • esmodule 的 bundless 构建工具

初版构建工具

grunt

最早的构建工具,构建工具的鼻祖
基于 nodejs 来开发的,借助nodejs实现跨系统,跨平台的操作文件系统
自动化的配置工具集,像官方所说的是一种 Task Runner,是基于任务的,整体配置json,由JSON配置设置驱动的。
基于 grunt 可以进行JS语法监测,或者合并一些JS文件,合并后的文件压缩,以及将我们预处理的sass,less文件进行编译
配置驱动、插件化、任务链

'use strict'
module.exports = function (grunt) {
    //构建的初始化配置
    grunt.initConfig({
        /*配置具体任务 */
        pkg: grunt.file.readIsON('package.json'),
        dirs: {
            src: 'path',
            dest: 'dest/<%= pkg.name >/<%= pkg.version 名>'
        },
        // clean任务(删除dest/test_grunt/0.0.1 目录下非min的文件)
        clean: {
            js: ['<%= dirs.dest &>/*.js', '!<%= dirs.dest %>/*.min.js'],
            css: ['<%= dirs,dest %>/*.css', '!<%= dirs.dest 名>/*.min.css'],
        },
        // copy任务(拷贝path目录下的文件到dest目录)
        copy: {
            main: {
                files: [
                    // includes files within path
                    {
                        expand: true,
                        src: ['path/*'],
                        dest: '<%= dirs.dest %>/',
                        filter: 'isFile',
                    },
                ],
            },
        },
        //concat任务(将dest目录下的a.js和b.js合并为built.js)
        concat: {
            options: {
                separator: '\n',
            },
            concatCss: {
                src: ['<%= dirs,dest &>/a.css', '<%= dirs.dest &>/path/b.css'],
                dest: '<%= dirs.dest %>/built.css',
            },
            concatJs: {
                src: ['<%= dirs,dest &>/a.js', '<%= dirs.dest &>/b.js'],
                dest: '<%= dirs.dest %>/built.is'
            }
        },
        // cssmin任务(压缩css)
        cssmin: {
            target: {
                files: [
                    {
                        expand: true,
                        cwd: '<%= dirs.dest %>',
                        src: ['*.css', '!*.min.css'],
                        dest: '<%= dirs.dest %>',
                        ext: '.min.css'
                    }
                ]
            },
        },
        // uglify任务(压缩js)
        uglify: {
            options: {
                mangle: {
                    except: ['jQuery', 'Backbone'],
                },
            },
            my_target: {
                files: {
                    '<%= dirs.dest %>/bulit.min.js': ['<%= dirs.dest %>/*.js']
                },
            },
        },
    })
    // 载入要使用的插件
    grunt.loadNpmTasks('grunt-contrib-clean')
    grunt.loadNpmTasks('grunt-contrib-copy')
    grunt.loadNpmTasks('grunt-contrib-concat')
    grunt.loadNpmTasks('grunt-contrib-cssmin')
    grunt.loadNpmTasks('grunt-contrib-uglify')

    //注册刚配置好的任务
    grunt.registerTask('cls', ['clean'])
    grunt.registerTask('cpy', ['copy'])
    grunt.registerTask('con', ['concat'])
    grunt.registerTask('cmpCSS', ['cssmin'])
    grunt.registerTask('cmpJS', ['uglify'])
    grunt.registerTask('default', ['copy', 'concat', 'cssmin', 'uglify', 'clean'])
}

缺点:
针对 文件处理模式

  • grunt 任务,基于磁盘文件操作,先读取 => 再处理 => 后写入

效率是非常低下的

grunt.initConfig({
   uglify: {
      files:{
     	'dest/output.min.js': ['src/input1.js','src/input2.js']
      }
   }
})

读取 less => 编译 css => 写入磁盘 => 读取 css => 压缩处理 => 写入磁盘

使用场景
  • 传统项目维护 已经是使用grunt来处理
  • 简单任务自动化 使用grunt也足够了

gulp

基于 nodejs 的流式前端构建工具。特点:代码驱动任务,高效流处理,基于task驱动
完成 测试,检查,合并,压缩 能力

采用管道机制

采用管道pipe机制处理文件,所有操作在内存中处理,基于内存流的,避免频繁io操作
在管道 pipe 中 =>使用 less 插件=>转成 css =>使用 minicss 插件压缩css => 写入磁盘,由于是在内存中完成的,因此效率提升

任务化配置与api简洁
gulp.task('css',()=>
	gulp.src('./src/css/**').pipe(cssmin()).pipe(gulp.dest('./dist/css'))
)

插件生态庞大,包含文件压缩,语法编译等

基于流式的高效性和插件驱动的灵活性

var gulp = require('gulp')
var pug = require('gulp-pug')
var less = require('gulp-less')
var minifyCss = require('gulp-csso')

gulp.task('html',function(){
	return gulp
	.src('client/templates/*.pug')
	.pipe(pug())
	.pipe(gulp.dest('build/html'))
})
gulp.task('css',function(){
	return gulp
		.src('client/templates/*.less')
		.pipe(less())
		.pipe(minifycss())
		.pipe(gulp.dest('build/css'))
})

gulp.task('default', ['html''css'])

现代打包构建工具基石–webpack

上篇文章中已说到了,这里就不再赘述了。

特性:基于各种各样配置,包含loader对文件进行编译处理,webpack内容当中,所有内容皆为模块,需要转译成JS模块,需要使用不同的loader进行处理,另外,还有插件的能力,webpack基于事件流的,集成自 tapable 的,学会开发自定义插件,了解compiler,complation 各自的有哪些钩子,并且钩子能做哪些事情,落地一些插件才行

基于webpack改进的构建工具

rollup 推荐

vue2,vue3,react,babel等,源码层面上,都是使用 rollup 做构建工具的
专注于 js 模块打包的工具
特点:高效性,轻量性,一般都是在前端 Library 基础类库工具函数等打包,打包出来的效果要优于webpack的,体积也要优于webpack。
对于基础类库/工具函数库需要被其他函数库引用,像引入 vue2,vue3,react。针对他们的诉求肯定是越小越好,没有用到的相关特性就不要打包进来了,所以 tree shaking 能力是必备的,能够对当前代码进行静态分析,esModule的导入导出,没有用到的功能(deadcode )就会精准剔除

  • 高效 tree shaking 能力

  • 减小包体积,避免冗余依赖,适用于按需加载的场景

  • 支持输出 ESM commonjs AMD IIFE UMD模块格式,满足不同环境需求
    配置时候也比较简单,只需要在配置文件中进行如下操作:

    rollup index.js -f cjs -o bundle.cjs.js #输出 CommonJS格式
    
  • 轻量化代码输出
    几乎不添加额外代码
    打包仅包含一些必要的函数,辅助代码

  • 强大的插件生态,vite线上发布使用rollup进行打包的,vite扩展了rollup插件生态,包含代码转换,依赖解析,压缩等场景

  • @rollup/plugin-babel

  • @rollup/plugin-terser 压缩代码

  • @rollup/plugin-commonjs,将commonjs => ESM

很多相关的插件
针对 rollup 有插件,没有loader,但是也能对 非 js 文件进行处理,有扩展的能力

  • transform 对代码进行转换
    • 语法转换
    • 添加额外功能
    • 等等
      因此在开发插件的时候,需要重点关注 transform 方法
举例说明

pnpm init

在这里插入图片描述

package.json
  • “rollup-plugin-cleaner”:“^1.0.0”, —— 清除当前目录下的dist文件的
  • “rollup-plugin-cleanup”:“^3.2.1”, —— 清除代码注释,删除无效的console等等
  • “rollup-plugin-postcss”:“^4.0.2” —— 针对css文件的插件
{
  "name": "about-builder",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build":"npx rollup -c rollup.config.mjs --watch"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies":{
    "parcel": "^2.13.0",
    "react":"^18.3.1",
    "react-dom":"^18.3.1",
    "rollup":"^4.27.4",
    "rollup-plugin-cleaner":"^1.0.0", 
    "rollup-plugin-cleanup":"^3.2.1",
    "rollup-plugin-postcss":"^4.0.2"
  }, 
  "devDependencies":{
    "process":"^0.11.10"
  }
}

rollup.config.mjs

使用rollup的话,就需要提供这样的一个配置文件

import postcss from "rollup-plugin-postcss"
import cleanup from "rollup-plugin-cleanup"
import cleaner from "rollup-plugin-cleaner"
import myExtractCssRollupPlugin from "./my-extract-css-rollup-plugin.mjs"


/** @type {import("rollup").RollupOptions} */
export default {
    input: 'src/index.js',
    output: [
        {
            file: 'build/esm.js',
            format: 'esm'
        },
        {
            file: 'build/cjs.js',
            format: 'cjs' //指定当前模块规范
        },
        {
            file: 'build/umd.js',
            name: 'Echo',
            format: 'umd'
        }
    ],
    plugins: [
        cleaner({
            targets: ['dist',"build"], //需清理的目录
            silent: false, //显示操作日志
            watch: true, //监听模式
            exclude: ['README.md'], //保留特定文件
        }),
        // 代码清理
        cleanup({
            comments: false,
            sourcemap: false,
            targets: ['build/*']
        }),
        // 处理css,将css内容从js文件中提取出来
        postcss({
            extract: true,
            extract: 'index.css'
        }),
        // 自定义插件
        myExtractCssRollupPlugin({
            filename: '666.css'
        })
    ]
}
my-extract-css-rollup-plugin.mjs
/*
 * 为什么 rollup 没有 loader 呢?
 * 因为 rollup 的 plugin 有 transform 方法,也就相当于 loader 的功能了。
 * Rollup 打包过程中对模块的代码进行转换操作
*/

const extractArr=[]

export default function myExtractCssRollupPlugin(opts) {
    return {
        name: 'my-extract-css-rollup-plugin',
        transform(code, id) {
            //在这里对代码进行转换操作
            if (!id.endsWith('.css')) {
                return null
            }
            // 将后缀为css的文件内容收集起来
            extractArr.push(code)
            
            return {
                // 转换后的代码
                code: '',
                // 可选的源映射信息,如果需要生成源映射的话
                map: { mappings: '' }
            }
        },
        //此方法在Rollup生成最终的输出文件之前被调用
        generateBundle(options, bundle) {
            this.emitFile({
                fileName: opts.filename,
                type:"asset",
                source:extractArr.join('/* #echo# */\n')
            })
        }
    }
}
src/index.js
import { add } from './utils.js'
// rollup 默认开启 tree shaking
import './index.css'

function main() {
    console.log(add(1, 3))
}

export default main
src/utils.js
import './utils.css'

function add(a, b) {
    return a + b;
}

export { add };
src/index.css
body{
    background: skyblue;
}
src/utils.css
.bbb{
    background: red;
}

执行

pnpm run build

得到:
在这里插入图片描述

build/cjs.js
'use strict';

function add(a, b) {
    return a + b;
}

function main() {
    console.log(add(1, 3));
}

module.exports = main;

build/esm.js
function add(a, b) {
    return a + b;
}

function main() {
    console.log(add(1, 3));
}

export { main as default };

build/umd.js
(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
    typeof define === 'function' && define.amd ? define(factory) :
    (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Echo = factory());
})(this, (function () { 'use strict';

    function add(a, b) {
        return a + b;
    }

    function main() {
        console.log(add(1, 3));
    }

    return main;

}));

build/index.css
.bbb{
    background: red;
}
body{
    background: skyblue;
}
build/666.css
export default undefined;/* #echo# */
export default undefined;
使用场景
  • 开发 js 库,工具函数
  • 需要 tree shaking 优化的项目
  • 生成环境打包 vite
不适用场景
  • 依赖非 js 资源 非常多

Parcel 不推荐

  • 完全零配置
  • 构建速度快

parcel 官网

举例说明

还是在上面的 about-builder 包下,使用 React 框架来写案例
在这里插入图片描述

parcel/index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="index.css">
</head>
<body>
    <div id="app"></div>
    <script type="module" src="./index.js"></script>
</body>
</html>
parcel/index.js
import { createRoot } from 'react-dom/client'
import App from './App.js'

const container = document.getElementById('app')
const root = createRoot(container)
root.render(<App />)
parcel/App.js
export function App() {
    return <h1>Hello World!</h1>
}
parcel/index.css
body{
    background-color: skyblue;
}
package.json

去掉 main 那一行,也就是:"main": "index.js"这个内容

执行:

npx parcel parcel/index.html

在这里插入图片描述

文件夹多了一个dist和.parcel-cache
在这里插入图片描述

页面:
在这里插入图片描述

热更新也是比较友好的

使用场景

适用小型项目

突破JS语言特性的构建工具

非 JS 语言相关的构建工具

SWC 推荐使用 √ - 平替babel

  • speedy web Compiler 快速web编译器
    => Compiler + bundler (编译+构建 所组成的)
    => bundler 有一定的缺陷,推荐使用 Compiler 编译 能力
    => 强调 快速 的能力,使用 rust 语言实现的,使用多线程
  1. 简历中做一些优化,针对 webpack 做一些常规的优化,像进行分包,还有像通过引入cache提升构建速度,像leo-plugins等方式,只是针对webpack本身所作的优化,但是现在
    webpack+babel 已经具备了性能瓶颈 => 优化措施:webpack+swc
    babel 对标 => swc
    babel-loader => swc-loader

  2. 文件比较多,使用 babel-loader 的话,需要经历 翻译、ast 是比较耗时的
    使用swc的话,性能会得到质的飞跃

  3. swc官方网站

  4. 性能表现原因:

    • rust 语言编写,编译时确定运行的行为,不像js是解释执行,解释成机器语言再执行机器语言。rust 是多线程的这样的一个能力
  5. 功能覆盖
    SWC 主要对 js 代码快速转换,核心将 es6+代码转换成 es5或者其他代码,在这过程中会进行代码压缩优化等相关的一些操作,比如swc能很好的处理箭头函数模板字符串解构赋值等es6+特性的转换,还有针对ts语言tsx语言等语言的处理,成熟度也是可以的

  6. 使用:简单转换代码
    @swc/core @swc/cli

    npx swc source.js -o dist.js

    const start = () => {
    	console.log('app started')
    }
    // 转为
    var start = function (){
    	console.log('app started')
    }
    
jsc-parser语法解析相关配置

使用 swc-loader 时候,需要着重注意 JSC 相关配置

swc-loader

  • JSC (javascript Compiler)
    配置项:
options:{
   //jsc相关能力配置
	"jsc":{
	    //当前需要转义哪些语言
		"parser":{
		 	//指定当前语言类型
			"syntax": "typescript", //ecmascript
			"tsx": true, //是否编译tsx
			"dynamicImport": true //是否支持动态导入
		}
	}
}
jsc-target 输出代码的es版本

配置对应的target
接着上面写:

options:{
   //jsc相关能力配置
	"jsc":{
	    //当前需要转义哪些语言
		"parser":{
		 	//指定当前语言类型
			"syntax": "typescript", //ecmascript
			"tsx": true, //是否编译tsx
			"dynamicImport": true //是否支持动态导入
		}
		//配置对应target
		"target": "es2015" //输出代码的es版本
		"transform":{     //代码转换
			"react":{
				"runtime":"automatic"
			},
			//启动代码优化
			"optimizer":{
				"simplify": true //简化
			}
		}
	}
}
典型配置案例

.swcrc 配置文件

{
  "jsc": {
    "parser": {
      "syntax": "typescript",
      "tsx": true,
      "decorators": true,
    },
    "transform":{     //代码转换
		"react":{
			"runtime":"automatic"
		}
	},
    "target": "es2018",
    //是否需要辅助函数
    "externalHelpers": true,
    "baseUrl": ".",
    "paths": {
    	"@/*": ["src/*"]
    }
  },
  "minify": true //进行代码压缩
}

也可以自己写一些插件

import{ readFilesync } from 'fs'
import { transform } from '@swc/core'

const run = async () => {
	const code = readFileSync('./source.js','utf-8')
	const result= await transform(code,{
		filename:'source.js',
	})
	//·输出编译后代码
	console.log(result.code)
}
run()

ESbuild - 作为工具去使用的

vite 在开发环境下,使用 esbuild 预构建依赖
由于并发处理包的构建是非常快的,因此才会使用,而JS本质是解释型语言,执行代码的时候需要一边将源码翻译成机器语言,一边调度执行。

  1. go编写程序,是编译型语言,少了动态解释过程

  2. 多线程
    go语言具备多线程能力,将所有的包都进行深度开发,因为JS是单线程,虽然也引入了webworker 做一些多线程的事情,但是还是有一些限制,比如说,go的多个线程之间是可以共享当前进程的内存空间,但是JS的webworker是不能共享进程内存空间的,如果想要数据共享的话,需要通过 postmessage 进行通信,但是这样的话,效率也比较低下的。因此,这也是JS的限制
    => 更高效的利用内存使用率 => 达到了更高的运行性能

  3. 全量定制
    比如,webpack中会用到babel实现ES5的版本转义,使用ESlint代码检查,使用tsc完成typescript代码转义,检查,使用less,scss等,这些使用插件去实现的。
    但是,esbuild中完全去重写,整套流程,工具都是重写的,意味着对这些文件的资源 tsx,jsx,js,ts等加载解析代码的生成逻辑,内部都会进行定制化开发,相对来说,成本也是非常高的,实现出来后,对编译的各个阶段都达到了非常好的性能。如果不去继续兼容webpack的loader,依然可能会达到不好的效果。
    webpack尤其针对 babel 的代码编译,会频繁的经历 string => AST => AST => string =>AST => string 这样的阶段,因此,esbuild重写了大多数转译工具,能够尽量共用相似的AST转换,减少AST结构的转换,进而提升内存利用率

  4. ESbuild 特性
    (1)极快的速度,无需缓存
    (2)支持 ES6 commonjs 模块
    (3)ES6 tree shaking
    (4)API 可以同时用于 js 和 go
    (5)兼容 ts,jsx语法
    (6)支持plugins
    这也是为什么 vite 使用 esbuild 作为包的转换

ESbuild官网
同时拷贝10个 three.js 库的扩展

在这里插入图片描述

基于ES Module的bundleless(no bundle)构建工具 => vite

http2 支持 多路复用 并发限制很大 10 50 100
浏览器 esm

基于bundle的解决方案

bundle based => entry 入口进行分析,分析当前的依赖内容,调用了哪些模块,对应的loader对当前进行处理 => modules,递归的完成这些模块的依赖分析 =>最终形成bundle => 启动 devServer 给到浏览器,然后浏览器去进行渲染

请添加图片描述

vite - 重点掌握

vite原理

而nobundle的思想:
本地启动一个服务,执行vite相关内容,会创建一个服务,启动devServer(本地请求资源服务),还有 websocket 两个服务(主要用于hm热更新)
no-bundle核心的两个特性:预构建、按需加载
请添加图片描述

使用按需加载的简单的vue3项目:

  1. 加载html,html中引入了main.js
    在这里插入图片描述
    还会引入 @vite/client,实现热更新
    在这里插入图片描述
  2. 加载client资源(热更新)
    监听消息
    在这里插入图片描述
    handleMessage方法:
    在这里插入图片描述
    在websocket中能看到payload.type,connect是建联,update是更新操作,等等。

先是建联:
在这里插入图片描述
更改 页面文字:
在这里插入图片描述
websocket会有update更新
在这里插入图片描述

类型是 js-update的话,会调用队列:
在这里插入图片描述
最终会发起 App.vue请求
App.vue请求会带着时间戳,不会复用之前的,避免了缓存的影响,就会拿到更改之后的数据替换之前的内容
在这里插入图片描述

  1. 加载main.js,引入了vue.js,style.css,等
    在这里插入图片描述

  2. 加载vue.js,style.css等,比如,style.css使用css插件做处理,创建style标签用在header当中
    在这里插入图片描述
    在这里插入图片描述

为什么vite之前没有,到2021年后才有这样的开发链路呢?
  1. http2.x 支持,多路复用
    之前webpack不拆包,将所有的都打包到一个bundle当中,热更新重新走整个链路的流程,最终形成bundle,然后再更新这个bundle,会受体积影响
    现在都是使用websocket,支持单文件的热更新
    多路复用
    http1.0 会对单个域名有tcp请求的限制,限制 6-8 tcp请求链接的数量,因此,将多个文件合并到一个文件当中进行处理,避免限制对有些请求发送不出去
    http2.x 有多路复用,同一个域名下对请求并发限制很大,10个,50个,100个同时请求服务器下的多个资源
  2. 浏览器支持 esm
    webpack时候还不支持 esm 这样的一个特性,需要经历编译这一层
    现在可以在浏览器中通过"import xxx"去加载到对应的资源内容
vite插件

使用 vite 创建 vue3 项目:

pnpm create vite my-vue3-app

在这里插入图片描述

使用vite构造的vue3项目:
在这里插入图片描述

package.json

这三个快捷指令
在这里插入图片描述

vite.config.js

内部集成了常见模块的插件,针对css等不需要单独额外处理
都是基于rollup插件去扩展的

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// 自定义插件
import myVitePlugin from './plugins/myPlugin'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue(), myVitePlugin()],
  test: {
    environment: 'jsdom',
    coverage: {
      reporter: ['text', 'json', 'html'],
      // 设置覆盖文件夹
      reportsDirectory: './coverage',
      // 检查每个文件的阈值
      perFile: true,
      // 设置代码覆盖率阈值
      lines: 75,
      functions: 75,
      branches: 75,
      statements: 75
    }
  }
})
自定义插件 -plugins/myPlugin.js

在工程当中,打印当前工程版本号

import path from 'path'
import fs from 'fs'

//控制台打印当前工程版本号
export default function myVitePlugin() {
    let version, config
    return {
        name: 'my-vite-plugin',
        configResolved(resolvedConfig) {
            config = resolvedConfig
            const pkgPath = path.resolve(config.root, 'package.json')
            const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'))
            version = pkg.version
        },
        buildStart() {
            console.log('当前工程版本号:1.0.0')
        },
        transform(code, id) {
            if (id.endsWith('main.js')) {
                const info = `console.log('当前工程版本号:${version}')`
                return `${code}\n${info}\n`
            }
        }
    }
}

在这里插入图片描述
在这里插入图片描述

vite插件的相关钩子
  • config 解析vite相关配置时候
  • configResolved 解析配置之后的钩子
  • configuerserver 配置开发服务器
  • handlehotupdate 执行热更新时候的钩子
通用钩子
  • options
  • buildstart 开始创建
  • transform 每个模块传入请求时调用
  • buildend 构建结束

rspack - 推荐尝试使用

基于 rust 语言,实现的高性能前端构建工具
特性:兼容webpack生态
完全从webpack配置快速迁移到 rust 的技术体系当中,在构建速度上得到了显著的提升

rspack 官网

在这里插入图片描述

示例:通过 rsbuild 创建一个工程

pnpm create rsbuild@latest

在这里插入图片描述
在这里插入图片描述

类似 vite:
在这里插入图片描述
在这里插入图片描述
rsbuild 与 webpack区别:

  1. 语言优势,rust 语言编译时会转为机器码,少了解释执行的过程
  2. 多线程
    rsbuild 与 vite 的区别:
  3. vite 在生产环境依赖 rollup,在开发环境使用 esbuild+热更新,no-bundle按需下载的思想

turpopack 国外的

相对来说使用的比较少

基于 rust
turpopack 官网

由 Vercel 赞助的
vercel
可以一键去部署自己的项目,无需写git-action的配置,已经内置了这样的能力,做了CI/CD

相关文章:

  • MySQL:InnoDB
  • 埃隆·马斯克如何通过开源创新塑造未来
  • 基于TCP Socket 实现心跳机制
  • 【AI提示词】API开发专家
  • Python operator 模块介绍
  • 关于 Java 预先编译(AOT)技术的详细说明,涵盖 GraalVM 的配置、Spring Boot 3.x 的集成、使用示例及优缺点对比
  • (二十)安卓开发中的事件监听(Listener)的使用方法梳理
  • 【全队项目】智能学术海报生成系统PosterGenius--多智能体辩论
  • 高精地图地图匹配定位算法(二)
  • 如何绕过WAF实现SQL注入攻击?​
  • [Windows] 字体渲染 mactype v2025.4.11
  • 2 VS Code 配置指南:C 语言开发环境搭建(含 MinGW-w64 编译器及关键扩展)
  • Web攻防—SSRF服务端请求伪造Gopher伪协议无回显利用
  • CATIA高效工作指南——常规配置篇(一)
  • MyBatis-Plus 核心功能
  • 《2025蓝桥杯C++B组:D:产值调整》
  • 14 - VDMA彩条显示实验
  • 二叉树深度解析:从基础概念到算法实现与应用
  • 04--网络属性设置与多路复用
  • 【HD-RK3576-PI】VNC 远程桌面连接
  • 江苏集团网站建设/东莞搜索引擎推广
  • 天津网站建设 Wordpress/企业seo推广外包
  • 怎么样做网站管理员/关键词排名怎么做好
  • 外贸网站建设公司价格/免费网站seo排名优化
  • asp网站开发四酷全书/谷歌seo综合查询
  • 网站设计费用/网络营销企业网站推广