Build Vue3 component library from 0 (7): use gulp to package component library and realize on-demand loading

Use gulp to package component libraries and implement on-demand loading

When we use the Vite library mode to package, vite will package all the style files into the same file, so we have to import all the style files every time to achieve the effect of importing on demand. So when packaging, we can not let vite package the style files, and the style files will be packaged with gulp. So this article will introduce how to use gulp to package style files, and how to load style files on demand.

Automatically import plugins on demand

Nowadays, the on-demand introduction of many component libraries is solved by plug-ins. For example, ElementPlus uses unplugin-vue-components and unplugin-auto-import. These two plug-ins can realize

import {
    
     Button } from "easyest";

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

In order to achieve on-demand introduction, the use of these plug-ins will not be expanded too much here, because the focus of this article is not here, and those who are interested can directly query the usage method unplugin-vue-components

delete package file

We all know that the previously packaged files need to be deleted before packaging, so we need to write a delete function first. Before that, we first create a script folder in components to store our script-related content, and the content in the build folder under script is the packaging-related content to be introduced in this article.
Create a new paths.ts in script/utils to maintain the component library path, remember to install it first

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

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

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

The delete package directory function can be placed in delpath.ts in bulid/utils. Note here that because the packaged easyest package is the package we will eventually release, we need to keep package.json and README.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;

在这里插入代码片use gulp

We need to use ts and the new es6 syntax, but gulp does not support it, so we need to install some dependencies to make gulp support these, where sucras allows us to execute gulp to use the latest syntax and support ts

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

In build/index.ts to perform the deletion process

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());

Add the script in the root directory easyest/package.json

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

Execute pnpm run build:easyest in the root directory and you will find that the files under easyest have been deleted

insert image description here
After deleting, you can start packaging styles

gulp packaging style

Because we use the style written by less, we need to install gulp-less, and at the same time install an auto-completion css prefix plug-in gulp-autoprefixer and their corresponding above files

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

Then write a package-style function, which uses the dest and src functions of gulp. I don’t know what it means. I’m happy to read the introduction of gulp in the previous article.

//打包样式
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`));
};

在这里插入代码片packaged components

Finally, write a function for packaging components. Here you need to write a tool function for executing commands, in 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);
  });
};

Then introduce the run function

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

Because packaged styles and packaged components can be parallelized, the final build/index.ts is

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()
  )
);

Finally, ignore the less file when vite is packaged, 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/],
      ...
  }

});

In order to better see the packaged effect, we can write a simple Icon component, the directory is as follows

Guess you like

Origin blog.csdn.net/weixin_45821809/article/details/130274151