Home  >  Article  >  Web Front-end  >  How does Vue3 use glup to package component libraries and implement on-demand loading?

How does Vue3 use glup to package component libraries and implement on-demand loading?

WBOY
WBOYforward
2023-05-12 14:58:141770browse

Use glup to package the component library 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 that we have to load them in full every time Importing all style files does not have the effect of importing them on demand. So when packaging, we can not let vite package the style files, and the style files will be packaged using gulp. So this article will introduce how to use gulp to package style files and how to load style files on demand.

Automatically introduce plug-ins on demand

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

import { Button } from "easyest";

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

to achieve on-demand introduction. I will not expand the use of these plug-ins too much here, because this article The focus of the article is not here. If you are interested, you can directly query the usage method unplugin-vue-components

Delete packaged files

We all know that before packaging, you need to delete the previously packaged files. , so you need to write a delete function first. Before that, we first create a new script folder in components to store our script-related content. The content in the build folder under script is the packaging-related content to be introduced in this article.

Create 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, "../../../");

Deleting the packaging directory function can be placed in delpath.ts in bulid/utils. Pay attention here. Because the packaged easyest package is the package we will eventually publish, we need to retain 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;

and use gulp

We need to use ts and the new es6 syntax, which is not supported by gulp, so we need to install some dependencies to make gulp support these. Sucras allows us to execute gulp to use the latest syntax and support ts

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

Execute the deletion process in 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());

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

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

Execute in the root directorypnpm run build:easyestYou will find that the files under easyest have been deleted

How does Vue3 use glup to package component libraries and implement on-demand loading?

After deletion, you can start packaging the style

gulp packaging style

Because we are using styles written by less, we need to install gulp-less, and at the same time install an auto-complete 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 packaged style function. The dest and src functions of gulp are used here. If you don’t know what it means, I would like 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`));
};

Packaging component

Finally write a function to package the component. Here you need to write a tool function to execute the command. Then introduce the run function 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);
  });
};

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

Because packaging styles and packaging components can be parallel, 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()
  )
);

The last vite package ignores the less file, 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 effect of packaging, we can write a simple Icon component, the directory is as follows

How does Vue3 use glup to package component libraries and implement on-demand loading?

The final root directory Execute pnpm run build to complete the packaging

How does Vue3 use glup to package component libraries and implement on-demand loading?

Since vite packaging ignores less file packaging, the packaged file encounters the .less file The import will be automatically skipped, so the import code has not changed

How does Vue3 use glup to package component libraries and implement on-demand loading?

But we have packaged the less file into a css file, so we need to change the .less in the code Change to .css

Add

 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"),
          });
        }
      },
    },
  ],

In the plugins in components/vite.config.ts, execute pnpm run build: easyest, and then look at the packaged file introduction

How does Vue3 use glup to package component libraries and implement on-demand loading?

At this time .less has been replaced by .css , after packaging is completed, the next thing to do is to publish it!

The above is the detailed content of How does Vue3 use glup to package component libraries and implement on-demand loading?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:yisu.com. If there is any infringement, please contact admin@php.cn delete