使用 glup 打包组件库并实现按需加载

当我们使用 Vite 库模式打包的时候,vite 会将样式文件全部打包到同一个文件中,这样的话我们每次都要全量引入所有样式文件做不到按需引入的效果。所以打包的时候我们可以不让 vite 打包样式文件,样式文件将使用 gulp 进行打包。那么本篇文章将介绍如何使用 gulp 打包样式文件,以及如何按需加载样式文件。

自动按需引入插件

现在很多组件库的按需引入都是借助插件来解决的,比如ElementPlus是使用unplugin-vue-componentsunplugin-auto-import,这两个插件可以实现

import { Button } from "easyest";

//相当于
import "easyest/es/src/button/style/index.css";
import "easyest/es/src/button/index.mjs";

从而实现按需引入,这里不再过多展开这些插件的使用,因为本篇文章的重点不在这里,感兴趣的可以直接去查询使用方式unplugin-vue-components

删除打包文件

我们都知道,在打包之前是需要将前面打包的文件删除的,所以需要先写一个删除函数。在此之前,我们先在 components 新建一个 script 文件夹用于存放我们的脚本相关内容,script 下的 build 文件夹里的内容则是本篇文章要介绍的打包相关内容。

在 script/utils 中新建 paths.ts 用于维护组件库路径,记得先安装

pnpm add @types/node -D -w
import { resolve } from "path";

//组件库根目录
export const componentPath = resolve(__dirname, "../../"); //pkg根目录
export const pkgPath = resolve(__dirname, "../../../");

删除打包目录函数可以放在 bulid/utils 中的 delpath.ts,注意这里因为打包后的 easyest 包是我们最终要发布的包,所以我们需要将package.jsonREADME.md保留下来

import fs from "fs";
import { resolve } from "path";
import { pkgPath } from "./paths";
//保留的文件
const stayFile = ["package.json", "README.md"]; const delPath = async (path: string) => {
let files: string[] = []; if (fs.existsSync(path)) {
files = fs.readdirSync(path); files.forEach(async (file) => {
let curPath = resolve(path, file); if (fs.statSync(curPath).isDirectory()) {
// recurse
if (file != "node_modules") await delPath(curPath);
} else {
// delete file
if (!stayFile.includes(file)) {
fs.unlinkSync(curPath);
}
}
}); if (path != `${pkgPath}/easyest`) fs.rmdirSync(path);
}
};
export default delPath;

使用 gulp

我们需要使用 ts 以及新的 es6 语法,而 gulp 是不支持的,所以我们需要安装一些依赖使得 gulp 支持这些,其中 sucras 让我们执行 gulp 可以使用最新语法并且支持 ts

pnpm i gulp @types/gulp sucrase -D -w

在 build/index.ts 来执行删除流程

import delPath from "../utils/delpath";
import { series, parallel } from "gulp";
import { pkgPath } from "../utils/paths";
//删除easyest export const removeDist = () => {
return delPath(`${pkgPath}/easyest`);
}; export default series(async () => removeDist());

在根目录 easyest/package.json 添加脚本

  "scripts": {
"build:easyest": "gulp -f packages/components/script/build/index.ts"
},

根目录下执行pnpm run build:easyest就会发现 easyest 下的文件被删除了

删除完之后就可以开始打包样式了

gulp 打包样式

因为我们用的是 less 写的样式,所以需要安装gulp-less,同时在安装一个自动补全 css 前缀插件gulp-autoprefixer以及它们对应的上面文件

pnpm add gulp-less @types/gulp-less gulp-autoprefixer @types/gulp-autoprefixer -D -w

然后写一个打包样式的函数,这里使用到了 gulp 的destsrc函数,不知道什么意思的乐意看上一篇文章 gulp 的介绍

//打包样式
export const buildStyle = () => {
return src(`${componentPath}/src/**/style/**.less`)
.pipe(less())
.pipe(autoprefixer())
.pipe(dest(`${pkgPath}/easyest/lib/src`))
.pipe(dest(`${pkgPath}/easyest/es/src`));
};

打包组件

最后再写一个打包组件的函数,这里需要写一个执行命令的工具函数,在 utils/run.ts

import { spawn } from "child_process";

export default async (command: string, path: string) => {
//cmd表示命令,args代表参数,如 rm -rf rm就是命令,-rf就为参数
const [cmd, ...args] = command.split(" ");
return new Promise((resolve, reject) => {
const app = spawn(cmd, args, {
cwd: path, //执行命令的路径
stdio: "inherit", //输出共享给父进程
shell: true, //mac不需要开启,windows下git base需要开启支持
});
//执行完毕关闭并resolve
app.on("close", resolve);
});
};

然后引入 run 函数

//打包组件
export const buildComponent = async () => {
run("pnpm run build", componentPath);
};

因为打包样式和打包组件可以并行,所以最后build/index.ts

import delPath from "../utils/delpath";
import { series, parallel, src, dest } from "gulp";
import { pkgPath, componentPath } from "../utils/paths";
import less from "gulp-less";
import autoprefixer from "gulp-autoprefixer";
import run from "../utils/run";
//删除dist export const removeDist = () => {
return delPath(`${pkgPath}/easyest`);
}; //打包样式
export const buildStyle = () => {
return src(`${componentPath}/src/**/style/**.less`)
.pipe(less())
.pipe(autoprefixer())
.pipe(dest(`${pkgPath}/easyest/lib/src`))
.pipe(dest(`${pkgPath}/easyest/es/src`));
}; //打包组件
export const buildComponent = async () => {
run("pnpm run build", componentPath);
};
export default series(
async () => removeDist(),
parallel(
async () => buildStyle(),
async () => buildComponent()
)
);

最后 vite 打包的时候忽略 less 文件,components/vite.config.ts

import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import dts from "vite-plugin-dts";
import DefineOptions from "unplugin-vue-define-options/vite";
export default defineConfig({
build: {
//打包文件目录
outDir: "es",
//压缩
//minify: false,
rollupOptions: {
//忽略打包vue和.less文件
external: ["vue", /\.less/],
...
} });

为了更好的看打包后的效果,我们可以再写一个简单的 Icon 组件,目录如下

最后根目录执行pnpm run build,即可完成打包

由于 vite 打包忽略了 less 文件打包,所以打包后的文件遇到.less 文件的引入会自动跳过,所以引入代码没变

但是我们已经将 less 文件打包成 css 文件了,所以我们需要将代码中的.less换成.css

在 components/vite.config.ts 中的 plugins 中新增

 plugins: [
vue(),
DefineOptions(),
dts({
entryRoot: "./src",
outputDir: ["../easyest/es/src", "../easyest/lib/src"],
//指定使用的tsconfig.json为我们整个项目根目录下,如果不配置,你也可以在components下新建tsconfig.json
tsConfigFilePath: "../../tsconfig.json",
}),
{
name: "style",
generateBundle(config, bundle) {
//这里可以获取打包后的文件目录以及代码code
const keys = Object.keys(bundle); for (const key of keys) {
const bundler: any = bundle[key as any];
//rollup内置方法,将所有输出文件code中的.less换成.css,因为我们当时没有打包less文件 this.emitFile({
type: "asset",
fileName: key, //文件名名不变
source: bundler.code.replace(/\.less/g, ".css"),
});
}
},
},
],

此时执行pnpm run build:easyest,然后再看打包后文件引入

此时.less已经被替换成了.css,打包完毕,接下来要做的就是发布了,下篇文章将介绍如何发布一个组件库,欢迎点赞+关注!

本篇文章对应代码地址使用 glup 打包组件库并实现按需加载

从0搭建Vue3组件库(七):使用 glup 打包组件库并实现按需加载的更多相关文章

  1. vue3.0使用ant-design-vue进行按需加载原来这么简单

    下载 ui库 yarn add ant-design-vue 默认是全局引入,打包后体积很大, 非常影响首屏加载速度, 按需加载 下载按需加载的插件;推荐使用cnpm cnpm install bab ...

  2. 仿ElementUI构建自己的Vue组件库用babel-plugin-component按需加载组件及自定义SASS主题

    最近使用ElementUI做项目的时候用Babel的插件babel-plugin-component做按需加载,使得组件打包的JS和CSS包体积大大缩小,加载速度也大大提升,所有想模仿做一个组件库也来 ...

  3. [转] 组件库按需加载 借助babel-plugin-import实现

    前段时间一直在基于webpack进行前端资源包的瘦身.在项目中基于路由进行代码分离,http://www.cnblogs.com/legu/p/7251562.html.对于公司内部的组件库,所有内容 ...

  4. 组件库按需加载 借助babel-plugin-import实现

    前段时间一直在基于webpack进行前端资源包的瘦身.在项目中基于路由进行代码分离,http://www.cnblogs.com/legu/p/7251562.html.对于公司内部的组件库,所有内容 ...

  5. React Router 4.0 + webpack 实现组件按需加载

    网上关于React Router 4.0的按需加载文章有很多,大致的思路都一样,但是其实具体实现起来却要根据自己的实际情况来定,这里主要介绍一下我的实现方式. 主要方式是通过Route组件的rende ...

  6. 快速搭建react项目骨架(按需加载、redux、axios、项目级目录等等)

    一.前言 最近整理了一下项目骨架,顺便自定义了一个脚手架,方便日后使用.我会从头开始,步骤一步步写明白,如果还有不清楚的可以评论区留言.先大致介绍一下这个骨架,我们采用 create-react-ap ...

  7. antd图标库按需加载的插件实现

    前景概要 antd是阿里出品的一款基于antd的UI组件库,使用简单,功能丰富,被广泛应用在中台项目开发中,虽然也出现了彩蛋事故,但不能否认antd本身的优秀,而我们公司在实际工作中也大量使用antd ...

  8. Vue3 使用 svg-sprite-loader 实现 svg 图标按需加载

    前面文章有讲到 svg 图标按需加载的优势以及 Vue 如何使用 vue-svg-icon 实现 svg 图标按需载入: https://www.cnblogs.com/Leophen/p/13201 ...

  9. vue项目引用 iView 组件——全局安装与按需加载

    框架的热度,出现了不少基于Vue的UI组件库,这次项目用到了 iView 这个组件库.使用方法官网很详细. 官网:https://www.iviewui.com/ 这篇文章主要是记录一下npm 全局安 ...

  10. Vue.js中用webpack合并打包多个组件并实现按需加载

    对于现在前端插件的频繁更新,所以多多少少要对组件化有点了解,下面这篇文章主要给大家介绍了在Vue.js中用webpack合并打包多个组件并实现按需加载的相关资料,需要的朋友可以参考下.   前言 随着 ...

随机推荐

  1. Mysql学习:4、DML命令(增删改查)及密码修改

    1.查询表中所有数据: select * from students; 2.插入数据: insert into students (id,name,email,address) values(1,'张 ...

  2. flutter 使用阿里iconfont图标库

    1. 打开Iconnfont,选择自己想要的图标添加到购物车! 2,在右上角点开购物车选择下载代码. 3. 解压下载的代码压缩包,我们可以看到一个iconfont.ttf 4. 在项目根目录下创建一个 ...

  3. IDEA的主题插件

    Xcode-Dark Theme

  4. SpringBatch生成的DB表SQL

    SQL: -- Autogenerated: do not edit this file DROP TABLE IF EXISTS BATCH_STEP_EXECUTION_CONTEXT; DROP ...

  5. spring boot2.3.0集成 thymelaf

    配置pom 如果是2.x的直接配置一个starter即可  <!-- ThymeLeaf 依赖 --><dependency>  <groupId>org.spri ...

  6. GPS数据处理

    GPS数据处理 题目内容: NMEA-0183协议是为了在不同的GPS(全球定位系统)导航设备中建立统一的BTCM(海事无线电技术委员会)标准,由美国国家海洋电子协会(NMEA-The Nationa ...

  7. CORS(cross origin resource sharing)

    1.什么是CORS 定义:跨域资源共享. 2.什么是跨域资源共享 允许浏览器可以从当前源服务器通过ajax访问另外一个源服务地址. 3.同源策略 是浏览器的一个安全功能,不同源的客户端脚本在没有明确的 ...

  8. IDEA2021 在jsp文件中 写out报错

    报错原因: 是因为没有关联好服务器: 解决方案 File --> Project structure --> Modules --> 选中当前的模板 --> Dependenc ...

  9. 关于group by的一个问题

    项目场景: 有时候,遇到数据库重复数据,需要将数据进行分组,并取出其中一条来展示,这时就需要用到group by语句.但是,如果mysql是高版本,当执行group by时,select的字段不属于g ...

  10. Mongodb+Stadio 3

    一.安装Mongodb  https://www.mongodb.com/download-center/community 请下载对应的系统 安装过程请不要选择 当所有的步骤值完成的时候,找到你的安 ...