¿Todavía no sabe cómo escribir un complemento de Vite?
Ahora que Vite se vuelve popular, ¿podemos hacer algo significativo, como escribir un complemento de Vite? ¿Qué le parece?
Resulta que podemos aprovechar la etapa inmadura del ecosistema de complementos de Vite para crear un complemento que nos agrade, que deje contentos a los líderes y a la comunidad, y avanzar de la mano con él.
Si le interesa Vite, puede visitar la columna: «Vite from entry to mastery»
En este artículo aprenderá
Cómo crear una plantilla de complemento de Vite
La función de cada hook del complemento de Vite
Orden de ejecución de los hooks del complemento de Vite
Cómo escribir su propio complemento
Conozca los complementos de Vite
1. Qué es un complemento de Vite
Vite es, en realidad, una nueva herramienta de desarrollo web front-end impulsada por ES Module nativo.
El complemento de Vite puede ampliar con facilidad lo que Vite no hace por sí mismo, como la compresión de archivos de imagen, la compatibilidad con CommonJS o la barra de progreso de empaquetado, entre otras cosas.
2. Por qué escribir un complemento de Vite
Creo que, a estas alturas, todos los compañeros ya conocen la configuración correspondiente de Webpack y los complementos habituales;
Como nueva herramienta de construcción front-end, Vite todavía es joven y tiene mucha extensibilidad, así que ¿por qué no avanzamos ahora de la mano con ella? ¿Hacemos algo más significativo para usted, para mí y para todos los demás?
Experiencia rápida
Si quiere escribir un complemento, debe empezar por crear un proyecto. La siguiente plantilla general de complementos de Vite se puede clonar directamente para usarla cuando escriba un complemento en el futuro;
Plantilla general del complemento en GitHub: entrada de demostración
Complemento en GitHub: entrada de demostración
Prioridad recomendada de gestor de paquetes: pnpm > yarn > npm > cnpm
En pocas palabras, ¡a empezar ya!
Crear una plantilla genérica de complemento de Vite
1. Inicializar
1.1 Cree una carpeta e inicialícela: simplemente siga las indicaciones de inicialización
mkdir vite-plugin-progress && cd vite-plugin-progress && pnpm init
1.2 Instalar TypeScript
pnpm i typescript @types/node -D
1.3 Configurar tsconfig.json
{
"compilerOptions": {
"module": "ESNext",
"target": "esnext",
"moduleResolution": "node",
"strict": true,
"declaration": true,
"noUnusedLocals": true,
"esModuleInterop": true,
"outDir": "dist",
"lib": ["ESNext"],
"sourceMap": false,
"noEmitOnError": true,
"noImplicitAny": false
},
"include": [
"src/*",
"*.d.ts"
],
"exclude": [
"node_modules",
"examples",
"dist"
]
}
1.4 Instalar Vite
// enter package.json
{
...
"devDependencies": {
"vite": "*"
}
...
}
2. Configurar ESLint y Prettier (opcional)
instalar ESLint
pnpm i eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin --save-dev
configurar .eslintrc: configure la conexión
Instalar Prettier (opcional)
pnpm i prettier eslint-config-prettier eslint-plugin-prettier --save-dev
configurar .prettierrc: configure la conexión
3. Agregar el archivo de entrada src/index.ts
import type { PluginOption } from 'vite';
export default function vitePluginTemplate(): PluginOption {
return {
// plugin name
name: 'vite-plugin-template',
// pre will be executed before post
enforce: 'pre', // post
// Indicate that they are only called in 'build' or 'serve' mode
apply: 'build', // apply can also be a function
config(config, { command }) {
console.log('here is the config hook');
},
configResolved(resolvedConfig) {
console.log('here is the configResolved hook');
},
configureServer(server) {
console.log('here is the configureServer hook');
},
transformIndexHtml(html) {
console.log('here is the transformIndexHtml hook');
},
}
}
A continuación se explican en detalle los hooks de función del complemento de Vite
En este punto, la plantilla básica ya está construida, pero pensemos ahora: ¿cómo deberíamos ejecutar este complemento?
Entonces necesitamos crear algunos ejemplos para ejecutar este código;
4. Crear el directorio examples
Aquí he creado tres conjuntos de demos de proyecto. Puede copiarlos directamente. No los explicaré en detalle aquí.
vite-react
vite-vue2
vite-vue3
Si su complemento necesita ejecutar más demos, cree el proyecto por su cuenta;
Luego debemos configurar el proyecto dentro de examples para hacer una depuración conjunta con el complemento del directorio raíz actual (a continuación se toma examples/vite-vue3 como ejemplo).
5. Configurar el proyecto examples/vite-vue3
Modificar examples/vite-vue3/package.json
{
...
"devDependencies": {
...
"vite": "link:../../node_modules/vite",
"vite-plugin-template": "link:../../"
}
}
Lo anterior significa:
Haga que la versión de Vite del proyecto examples/vite-vue3 coincida con la versión del directorio raíz vite-plugin-template;
Al mismo tiempo, apunte el vite-plugin-template del proyecto examples/vite-vue3 al complemento desarrollado en su directorio raíz actual;
Importar el complemento: examples/vite-vue3/vite.config.ts
import template from 'vite-plugin-template';
export default defineConfig({
...
plugins: [vue(), template()],
...
});
Instalar: cd examples/vite-vue3 && pnpm install
cd examples/vite-vue3 && pnpm install
Nota: la configuración de examples/vite-vue2 y examples/vite-react es igual a esta
Reflexión:
En este punto, reflexionemos de nuevo. Ya configuramos el proyecto en examples/vite-vue3, pero ¿cómo deberíamos ejecutarlo?
¿Ir directamente al directorio examples/vite-vue3 y ejecutar pnpm run build o pnpm run dev?
Obviamente esto no se puede ejecutar con éxito, porque el src/index.ts de nuestro directorio raíz no se ejecuta de forma directa, así que necesitamos compilar el archivo .ts a un archivo .js;
Entonces, ¿cómo lo resolvemos?
Entonces tenemos que usar una herramienta pequeña y sin configuración: tsup.
6. Instalar tsup, configurar y ejecutar el comando
tsup es una herramienta de compilación ligera y sin configuración, impulsada por esbuild;
Al mismo tiempo, puede convertir directamente archivos .ts y .tsx a distintos formatos: esm, cjs e iife;
instalar tsup
pnpm i tsup -D
Configurado en el package.json del directorio raíz
{
...
"scripts": {
"dev": "pnpm run build -- --watch --ignore-watch examples",
"build": "tsup src/index.ts --dts --format cjs,esm",
"example:react": "cd examples/vite-react && pnpm run build",
"example:vue2": "cd examples/vite-vue2 && pnpm run build",
"example:vue3": "cd examples/vite-vue3 && pnpm run build"
},
...
}
7. Ejecución en el entorno de desarrollo
Operación del entorno de desarrollo: monitoreo en tiempo real de la modificación de archivos y reempaquetado (hot update)
pnpm run dev
Ejecute cualquier proyecto de examples (tomando vite-vue3 como ejemplo)
pnpm run example:vue3
Aviso:
Si su complemento solo se ejecutará en tiempo de compilación, establezca "example:vue3": "cd examples/vite-vue3 && pnpm run build";
De lo contrario, ejecute pnpm run dev
salida:
A partir de aquí, puede desarrollar mientras ejecuta. You Yuxi dijo que era genial cuando lo vio.
8. Post
Instalar bumpp para agregar control de versiones y etiquetas
pnpm i bumpp -D
configurar package.json
{
...
"scripts": {
...
"prepublishOnly": "pnpm run build",
"release": "npx bumpp --push --tag --commit && pnpm publish",
},
...
}
Ejecute la publicación después de desarrollar el complemento
# first step
pnpm run prepublishOnly
# second step
pnpm run release
Y con esto, nuestra plantilla de complemento de Vite está escrita; puede clonar directamente la plantilla vite-plugin-template para usarla;
Si le interesan los hooks de complemento de Vite y la implementación de un complemento de Vite real, puede seguir leyendo;
Hooks de complemento para Vite
1. Hooks exclusivos de Vite
enforce: el valor puede ser pre o post; pre se ejecuta antes que post;
apply: el valor puede ser build o serve, o bien una función, y especifica que solo se llaman en modo build o serve;
config(config, env): permite modificar la configuración relacionada con Vite antes de que se analice. El hook recibe la configuración original del usuario config y una variable env que describe el entorno de configuración;
configResolved(resolvedConfig): se llama después de que se resuelve la configuración de Vite. Use este hook para leer y almacenar la configuración final resuelta. Es útil cuando un complemento necesita hacer algo distinto según el comando que se ejecute.
configure reServer(server): se usa principalmente para configurar el servidor de desarrollo y agregar middleware personalizado para dev-server (aplicación connect);
transformIndexHtml(html): hook dedicado a transformar index.html. El hook recibe la cadena HTML actual y el contexto de conversión;
handleHotUpdate(ctx): ejecuta una actualización HMR personalizada; puede enviar eventos personalizados al cliente a través de ws;
2. Fase de construcción de los hooks comunes de Vite y Rollup
options(options): se llama cuando inicia el servidor: obtiene y manipula las opciones de Rollup; en sentido estricto, se ejecuta antes de la fase de compilación;
buildStart(options): se llama cada vez que inicia una compilación;
resolveId(source, importer, options): se llama por cada solicitud de módulo entrante; crea una función de confirmación personalizada que puede usarse para localizar dependencias de terceros;
load(id): se llama por cada solicitud de módulo entrante; el cargador puede personalizarse y usarse para devolver contenido personalizado;
transform(code, id): se llama en cada solicitud de módulo entrante; se usa principalmente para transformar un solo módulo;
buildEnd(): se llama después del fin de la fase de compilación, donde el fin de la compilación solo significa que todos los módulos están compilados;
3. Etapa de salida del hook general de Vite y Rollup
outputOptions(options): acepta parámetros de salida;
renderStart(outputOptions, inputOptions): se activa cada vez que se llaman bundle.generate y bundle.write;
augmentChunkHash(chunkInfo): se usa para agregar un hash al chunk;
renderChunk(code, chunk, options): se activa cuando se transforma un chunk individual; Rollup lo llama al generar cada archivo de chunk;
generateBundle(options, bundle, isWrite): activa este hook justo antes de llamar a bundle.write;
writeBundle(options, bundle): después de llamar a bundle.write, una vez que todos los chunks se escriben en el archivo, writeBundle se llama al final;
closeBundle(): se llama cuando se cierra el servidor
4. Orden de ejecución de los hooks de función del complemento (como se muestra a continuación)
5. Orden de ejecución de los complementos
Manejo de alias Alias
Complemento de usuario con enforce: 'pre'
Complementos principales de Vite
Complemento de usuario sin enforce
Complementos de compilación de Vite
Complemento de usuario con enforce: 'post'
Complementos posteriores de compilación de Vite (minify, manifest, reporting)
Escriba un complemento de Vite a mano
A continuación se toma como ejemplo el complemento de barra de progreso de empaquetado de Vite;
Dirección del complemento: github. Si le agrada, puede dejar su star ⭐️
Vite incluyó oficialmente el complemento en la documentación oficial: dirección del enlace
Como el enfoque de este artículo no es el proceso detallado de implementación de este complemento, aquí solo se incluye el código fuente como referencia. La explicación detallada se dará en el próximo artículo: ¡esté atento!
inde.ts
import type { PluginOption } from 'vite';
import colors from 'picocolors';
import progress from 'progress';
import rd from 'rd';
import { isExists, getCacheData, setCacheData } from './cache';
type Omit = Pick>;
type Merge = Omit> & N;
type PluginOptions = Merge<
ProgressBar.ProgressBarOptions,
{
/**
* total number of ticks to complete
* @default 100
*/
total?: number;
/**
* The format of the progress bar
*/
format?: string;
}
>;
export default function viteProgressBar(options?: PluginOptions): PluginOption {
const { cacheTransformCount, cacheChunkCount } = getCacheData()
let bar: progress;
const stream = options?.stream || process.stderr;
let outDir: string;
let transformCount = 0
let chunkCount = 0
let transformed = 0
let fileCount = 0
let lastPercent = 0
let percent = 0
return {
name: 'vite-plugin-progress',
enforce: 'pre',
apply: 'build',
config(config, { command }) {
if (command === 'build') {
config.logLevel = 'silent';
outDir = config.build?.outDir || 'dist';
options = {
width: 40,
...options
};
options.total = options?.total || 100;
const transforming = isExists ? `${colors.magenta('Transforms:')} :transformCur/:transformTotal | ` : ''
const chunks = isExists ? `${colors.magenta('Chunks:')} :chunkCur/:chunkTotal | ` : ''
const barText = `${colors.cyan(`[:bar]`)}`
const barFormat =
options.format ||
`${colors.green('Bouilding')} ${barText} :percent | ${transforming}${chunks}Time: :elapseds`
delete options.format;
bar = new progress(barFormat, options as ProgressBar.ProgressBarOptions);
// not cache: Loop files in src directory
if (!isExists) {
const readDir = rd.readSync('src');
readDir.forEach((item) => reg.test(item) && fileCount++);
}
}
},
transform(code, id) {
transformCount++
// not cache
if(!isExists) {
const reg = /node_modules/gi;
if (!reg.test(id) && percent < 0.25) {
transformed++
percent = +(transformed / (fileCount * 2)).toFixed(2)
percent < 0.8 && (lastPercent = percent)
}
if (percent >= 0.25 && lastPercent <= 0.65) {
lastPercent = +(lastPercent + 0.001).toFixed(4)
}
}
// go cache
if (isExists) runCachedData()
bar.update(lastPercent, {
transformTotal: cacheTransformCount,
transformCur: transformCount,
chunkTotal: cacheChunkCount,
chunkCur: 0,
})
return {
code,
map: null
};
},
renderChunk() {
chunkCount++
if (lastPercent <= 0.95)
isExists ? runCachedData() : (lastPercent = +(lastPercent + 0.005).toFixed(4))
bar.update(lastPercent, {
transformTotal: cacheTransformCount,
transformCur: transformCount,
chunkTotal: cacheChunkCount,
chunkCur: chunkCount,
})
return null
},
closeBundle() {
// close progress
bar.update(1)
bar.terminate()
// set cache data
setCacheData({
cacheTransformCount: transformCount,
cacheChunkCount: chunkCount,
})
// out successful message
stream.write(
`${colors.cyan(colors.bold(`Build successful. Please see ${outDir} directory`))}`
);
stream.write(' ');
stream.write(' ');
}
};
/**
* run cache data of progress
*/
function runCachedData() {
if (transformCount === 1) {
stream.write(' ');
bar.tick({
transformTotal: cacheTransformCount,
transformCur: transformCount,
chunkTotal: cacheChunkCount,
chunkCur: 0,
})
}
transformed++
percent = lastPercent = +(transformed / (cacheTransformCount + cacheChunkCount)).toFixed(2)
}
}
cache.ts
import fs from 'fs';
import path from 'path';
const dirPath = path.join(process.cwd(), 'node_modules', '.progress');
const filePath = path.join(dirPath, 'index.json');
export interface ICacheData {
/**
* Transform all count
*/
cacheTransformCount: number;
/**
* chunk all count
*/
cacheChunkCount: number
}
/**
*It has been cached
* @return boolean
*/
export const isExists = fs.existsSync(filePath) || false;
/**
* Get cached data
* @returns ICacheData
*/
export const getCacheData = (): ICacheData => {
if (!isExists) return {
cacheTransformCount: 0,
cacheChunkCount: 0
};
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
};
/**
* Set the data to be cached
* @returns
*/
export const setCacheData = (data: ICacheData) => {
!isExists && fs.mkdirSync(dirPath);
fs.writeFileSync(filePath, JSON.stringify(data));
};
por último
Esta serie tendrá actualizaciones continuas. En cuanto a la columna completa «Vite From Beginner to Mastery», la explicaré principalmente desde los siguientes aspectos: ¡esté atento!
Estimados, ya lo han visto todo aquí, ¿por qué no dejan su me gusta?👍.markdown-body pre,.markdown-body pre>code.hljs{color:#333;background:#f8f8f8}.hljs-comment,.hljs- quote{color:#998;font-style:italic}.hljs-keyword,.hljs-selector-tag,.hljs-subst{color:#333;font-weight:700}.hljs-literal,.hljs-number ,.hljs-tag .hljs-attr,.hljs-template-variable,.hljs-variable{color:teal}.hljs-doctag,.hljs-string{color:#d14}.hljs-section,.hljs-selector -id,.hljs-title{color:#900;font-weight:700}.hljs-subst{font-weight:400}.hljs-class .hljs-title,.hljs-type{color:#458;font -weight:700}.hljs-attribute,.hljs-name,.hljs-tag{color:navy;font-weight:400}.hljs-link,.hljs-regexp{color:#009926}.hljs-bullet, .hljs-symbol{color:#990073}.hljs-built_in,.hljs-builtin-name{color:#0086b3}.hljs-meta{color:#999;font-weight:700}.hljs-deletion{background: #fdd}.hljs-addition{background:#dfd}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700} Categoría: Front-end Etiquetas: Front-end Vite Los artículos se incluyen en la columna:
Vite from entry to mastery
Vite (se pronuncia de forma similar a [weɪt], que significa ligero) es una herramienta de construcción front-end para el desarrollo web impulsada por ES Module nativo.
Tiene las siguientes características:
💡 Arranque del servicio extremadamente rápido;
⚡️ Hot reload ligero y rápido;
🛠️ Funciones abundantes;
📦 Compilación optimizada;
🔩 Complemento universal;
🔑 API totalmente tipada.
Resulta que podemos aprovechar la etapa inmadura del ecosistema de complementos de Vite para crear un complemento que nos agrade, que deje contentos a los líderes y a la comunidad, y avanzar de la mano con él.
Si le interesa Vite, puede visitar la columna: «Vite from entry to mastery»
En este artículo aprenderá
Cómo crear una plantilla de complemento de Vite
La función de cada hook del complemento de Vite
Orden de ejecución de los hooks del complemento de Vite
Cómo escribir su propio complemento
Conozca los complementos de Vite
1. Qué es un complemento de Vite
Vite es, en realidad, una nueva herramienta de desarrollo web front-end impulsada por ES Module nativo.
El complemento de Vite puede ampliar con facilidad lo que Vite no hace por sí mismo, como la compresión de archivos de imagen, la compatibilidad con CommonJS o la barra de progreso de empaquetado, entre otras cosas.
2. Por qué escribir un complemento de Vite
Creo que, a estas alturas, todos los compañeros ya conocen la configuración correspondiente de Webpack y los complementos habituales;
Como nueva herramienta de construcción front-end, Vite todavía es joven y tiene mucha extensibilidad, así que ¿por qué no avanzamos ahora de la mano con ella? ¿Hacemos algo más significativo para usted, para mí y para todos los demás?
Experiencia rápida
Si quiere escribir un complemento, debe empezar por crear un proyecto. La siguiente plantilla general de complementos de Vite se puede clonar directamente para usarla cuando escriba un complemento en el futuro;
Plantilla general del complemento en GitHub: entrada de demostración
Complemento en GitHub: entrada de demostración
Prioridad recomendada de gestor de paquetes: pnpm > yarn > npm > cnpm
En pocas palabras, ¡a empezar ya!
Crear una plantilla genérica de complemento de Vite
1. Inicializar
1.1 Cree una carpeta e inicialícela: simplemente siga las indicaciones de inicialización
mkdir vite-plugin-progress && cd vite-plugin-progress && pnpm init
1.2 Instalar TypeScript
pnpm i typescript @types/node -D
1.3 Configurar tsconfig.json
{
"compilerOptions": {
"module": "ESNext",
"target": "esnext",
"moduleResolution": "node",
"strict": true,
"declaration": true,
"noUnusedLocals": true,
"esModuleInterop": true,
"outDir": "dist",
"lib": ["ESNext"],
"sourceMap": false,
"noEmitOnError": true,
"noImplicitAny": false
},
"include": [
"src/*",
"*.d.ts"
],
"exclude": [
"node_modules",
"examples",
"dist"
]
}
1.4 Instalar Vite
// enter package.json
{
...
"devDependencies": {
"vite": "*"
}
...
}
2. Configurar ESLint y Prettier (opcional)
instalar ESLint
pnpm i eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin --save-dev
configurar .eslintrc: configure la conexión
Instalar Prettier (opcional)
pnpm i prettier eslint-config-prettier eslint-plugin-prettier --save-dev
configurar .prettierrc: configure la conexión
3. Agregar el archivo de entrada src/index.ts
import type { PluginOption } from 'vite';
export default function vitePluginTemplate(): PluginOption {
return {
// plugin name
name: 'vite-plugin-template',
// pre will be executed before post
enforce: 'pre', // post
// Indicate that they are only called in 'build' or 'serve' mode
apply: 'build', // apply can also be a function
config(config, { command }) {
console.log('here is the config hook');
},
configResolved(resolvedConfig) {
console.log('here is the configResolved hook');
},
configureServer(server) {
console.log('here is the configureServer hook');
},
transformIndexHtml(html) {
console.log('here is the transformIndexHtml hook');
},
}
}
A continuación se explican en detalle los hooks de función del complemento de Vite
En este punto, la plantilla básica ya está construida, pero pensemos ahora: ¿cómo deberíamos ejecutar este complemento?
Entonces necesitamos crear algunos ejemplos para ejecutar este código;
4. Crear el directorio examples
Aquí he creado tres conjuntos de demos de proyecto. Puede copiarlos directamente. No los explicaré en detalle aquí.
vite-react
vite-vue2
vite-vue3
Si su complemento necesita ejecutar más demos, cree el proyecto por su cuenta;
Luego debemos configurar el proyecto dentro de examples para hacer una depuración conjunta con el complemento del directorio raíz actual (a continuación se toma examples/vite-vue3 como ejemplo).
5. Configurar el proyecto examples/vite-vue3
Modificar examples/vite-vue3/package.json
{
...
"devDependencies": {
...
"vite": "link:../../node_modules/vite",
"vite-plugin-template": "link:../../"
}
}
Lo anterior significa:
Haga que la versión de Vite del proyecto examples/vite-vue3 coincida con la versión del directorio raíz vite-plugin-template;
Al mismo tiempo, apunte el vite-plugin-template del proyecto examples/vite-vue3 al complemento desarrollado en su directorio raíz actual;
Importar el complemento: examples/vite-vue3/vite.config.ts
import template from 'vite-plugin-template';
export default defineConfig({
...
plugins: [vue(), template()],
...
});
Instalar: cd examples/vite-vue3 && pnpm install
cd examples/vite-vue3 && pnpm install
Nota: la configuración de examples/vite-vue2 y examples/vite-react es igual a esta
Reflexión:
En este punto, reflexionemos de nuevo. Ya configuramos el proyecto en examples/vite-vue3, pero ¿cómo deberíamos ejecutarlo?
¿Ir directamente al directorio examples/vite-vue3 y ejecutar pnpm run build o pnpm run dev?
Obviamente esto no se puede ejecutar con éxito, porque el src/index.ts de nuestro directorio raíz no se ejecuta de forma directa, así que necesitamos compilar el archivo .ts a un archivo .js;
Entonces, ¿cómo lo resolvemos?
Entonces tenemos que usar una herramienta pequeña y sin configuración: tsup.
6. Instalar tsup, configurar y ejecutar el comando
tsup es una herramienta de compilación ligera y sin configuración, impulsada por esbuild;
Al mismo tiempo, puede convertir directamente archivos .ts y .tsx a distintos formatos: esm, cjs e iife;
instalar tsup
pnpm i tsup -D
Configurado en el package.json del directorio raíz
{
...
"scripts": {
"dev": "pnpm run build -- --watch --ignore-watch examples",
"build": "tsup src/index.ts --dts --format cjs,esm",
"example:react": "cd examples/vite-react && pnpm run build",
"example:vue2": "cd examples/vite-vue2 && pnpm run build",
"example:vue3": "cd examples/vite-vue3 && pnpm run build"
},
...
}
7. Ejecución en el entorno de desarrollo
Operación del entorno de desarrollo: monitoreo en tiempo real de la modificación de archivos y reempaquetado (hot update)
pnpm run dev
Ejecute cualquier proyecto de examples (tomando vite-vue3 como ejemplo)
pnpm run example:vue3
Aviso:
Si su complemento solo se ejecutará en tiempo de compilación, establezca "example:vue3": "cd examples/vite-vue3 && pnpm run build";
De lo contrario, ejecute pnpm run dev
salida:
A partir de aquí, puede desarrollar mientras ejecuta. You Yuxi dijo que era genial cuando lo vio.
8. Post
Instalar bumpp para agregar control de versiones y etiquetas
pnpm i bumpp -D
configurar package.json
{
...
"scripts": {
...
"prepublishOnly": "pnpm run build",
"release": "npx bumpp --push --tag --commit && pnpm publish",
},
...
}
Ejecute la publicación después de desarrollar el complemento
# first step
pnpm run prepublishOnly
# second step
pnpm run release
Y con esto, nuestra plantilla de complemento de Vite está escrita; puede clonar directamente la plantilla vite-plugin-template para usarla;
Si le interesan los hooks de complemento de Vite y la implementación de un complemento de Vite real, puede seguir leyendo;
Hooks de complemento para Vite
1. Hooks exclusivos de Vite
enforce: el valor puede ser pre o post; pre se ejecuta antes que post;
apply: el valor puede ser build o serve, o bien una función, y especifica que solo se llaman en modo build o serve;
config(config, env): permite modificar la configuración relacionada con Vite antes de que se analice. El hook recibe la configuración original del usuario config y una variable env que describe el entorno de configuración;
configResolved(resolvedConfig): se llama después de que se resuelve la configuración de Vite. Use este hook para leer y almacenar la configuración final resuelta. Es útil cuando un complemento necesita hacer algo distinto según el comando que se ejecute.
configure reServer(server): se usa principalmente para configurar el servidor de desarrollo y agregar middleware personalizado para dev-server (aplicación connect);
transformIndexHtml(html): hook dedicado a transformar index.html. El hook recibe la cadena HTML actual y el contexto de conversión;
handleHotUpdate(ctx): ejecuta una actualización HMR personalizada; puede enviar eventos personalizados al cliente a través de ws;
2. Fase de construcción de los hooks comunes de Vite y Rollup
options(options): se llama cuando inicia el servidor: obtiene y manipula las opciones de Rollup; en sentido estricto, se ejecuta antes de la fase de compilación;
buildStart(options): se llama cada vez que inicia una compilación;
resolveId(source, importer, options): se llama por cada solicitud de módulo entrante; crea una función de confirmación personalizada que puede usarse para localizar dependencias de terceros;
load(id): se llama por cada solicitud de módulo entrante; el cargador puede personalizarse y usarse para devolver contenido personalizado;
transform(code, id): se llama en cada solicitud de módulo entrante; se usa principalmente para transformar un solo módulo;
buildEnd(): se llama después del fin de la fase de compilación, donde el fin de la compilación solo significa que todos los módulos están compilados;
3. Etapa de salida del hook general de Vite y Rollup
outputOptions(options): acepta parámetros de salida;
renderStart(outputOptions, inputOptions): se activa cada vez que se llaman bundle.generate y bundle.write;
augmentChunkHash(chunkInfo): se usa para agregar un hash al chunk;
renderChunk(code, chunk, options): se activa cuando se transforma un chunk individual; Rollup lo llama al generar cada archivo de chunk;
generateBundle(options, bundle, isWrite): activa este hook justo antes de llamar a bundle.write;
writeBundle(options, bundle): después de llamar a bundle.write, una vez que todos los chunks se escriben en el archivo, writeBundle se llama al final;
closeBundle(): se llama cuando se cierra el servidor
4. Orden de ejecución de los hooks de función del complemento (como se muestra a continuación)
5. Orden de ejecución de los complementos
Manejo de alias Alias
Complemento de usuario con enforce: 'pre'
Complementos principales de Vite
Complemento de usuario sin enforce
Complementos de compilación de Vite
Complemento de usuario con enforce: 'post'
Complementos posteriores de compilación de Vite (minify, manifest, reporting)
Escriba un complemento de Vite a mano
A continuación se toma como ejemplo el complemento de barra de progreso de empaquetado de Vite;
Dirección del complemento: github. Si le agrada, puede dejar su star ⭐️
Vite incluyó oficialmente el complemento en la documentación oficial: dirección del enlace
Como el enfoque de este artículo no es el proceso detallado de implementación de este complemento, aquí solo se incluye el código fuente como referencia. La explicación detallada se dará en el próximo artículo: ¡esté atento!
inde.ts
import type { PluginOption } from 'vite';
import colors from 'picocolors';
import progress from 'progress';
import rd from 'rd';
import { isExists, getCacheData, setCacheData } from './cache';
type Omit
type Merge
type PluginOptions = Merge<
ProgressBar.ProgressBarOptions,
{
/**
* total number of ticks to complete
* @default 100
*/
total?: number;
/**
* The format of the progress bar
*/
format?: string;
}
>;
export default function viteProgressBar(options?: PluginOptions): PluginOption {
const { cacheTransformCount, cacheChunkCount } = getCacheData()
let bar: progress;
const stream = options?.stream || process.stderr;
let outDir: string;
let transformCount = 0
let chunkCount = 0
let transformed = 0
let fileCount = 0
let lastPercent = 0
let percent = 0
return {
name: 'vite-plugin-progress',
enforce: 'pre',
apply: 'build',
config(config, { command }) {
if (command === 'build') {
config.logLevel = 'silent';
outDir = config.build?.outDir || 'dist';
options = {
width: 40,
...options
};
options.total = options?.total || 100;
const transforming = isExists ? `${colors.magenta('Transforms:')} :transformCur/:transformTotal | ` : ''
const chunks = isExists ? `${colors.magenta('Chunks:')} :chunkCur/:chunkTotal | ` : ''
const barText = `${colors.cyan(`[:bar]`)}`
const barFormat =
options.format ||
`${colors.green('Bouilding')} ${barText} :percent | ${transforming}${chunks}Time: :elapseds`
delete options.format;
bar = new progress(barFormat, options as ProgressBar.ProgressBarOptions);
// not cache: Loop files in src directory
if (!isExists) {
const readDir = rd.readSync('src');
readDir.forEach((item) => reg.test(item) && fileCount++);
}
}
},
transform(code, id) {
transformCount++
// not cache
if(!isExists) {
const reg = /node_modules/gi;
if (!reg.test(id) && percent < 0.25) {
transformed++
percent = +(transformed / (fileCount * 2)).toFixed(2)
percent < 0.8 && (lastPercent = percent)
}
if (percent >= 0.25 && lastPercent <= 0.65) {
lastPercent = +(lastPercent + 0.001).toFixed(4)
}
}
// go cache
if (isExists) runCachedData()
bar.update(lastPercent, {
transformTotal: cacheTransformCount,
transformCur: transformCount,
chunkTotal: cacheChunkCount,
chunkCur: 0,
})
return {
code,
map: null
};
},
renderChunk() {
chunkCount++
if (lastPercent <= 0.95)
isExists ? runCachedData() : (lastPercent = +(lastPercent + 0.005).toFixed(4))
bar.update(lastPercent, {
transformTotal: cacheTransformCount,
transformCur: transformCount,
chunkTotal: cacheChunkCount,
chunkCur: chunkCount,
})
return null
},
closeBundle() {
// close progress
bar.update(1)
bar.terminate()
// set cache data
setCacheData({
cacheTransformCount: transformCount,
cacheChunkCount: chunkCount,
})
// out successful message
stream.write(
`${colors.cyan(colors.bold(`Build successful. Please see ${outDir} directory`))}`
);
stream.write(' ');
stream.write(' ');
}
};
/**
* run cache data of progress
*/
function runCachedData() {
if (transformCount === 1) {
stream.write(' ');
bar.tick({
transformTotal: cacheTransformCount,
transformCur: transformCount,
chunkTotal: cacheChunkCount,
chunkCur: 0,
})
}
transformed++
percent = lastPercent = +(transformed / (cacheTransformCount + cacheChunkCount)).toFixed(2)
}
}
cache.ts
import fs from 'fs';
import path from 'path';
const dirPath = path.join(process.cwd(), 'node_modules', '.progress');
const filePath = path.join(dirPath, 'index.json');
export interface ICacheData {
/**
* Transform all count
*/
cacheTransformCount: number;
/**
* chunk all count
*/
cacheChunkCount: number
}
/**
*It has been cached
* @return boolean
*/
export const isExists = fs.existsSync(filePath) || false;
/**
* Get cached data
* @returns ICacheData
*/
export const getCacheData = (): ICacheData => {
if (!isExists) return {
cacheTransformCount: 0,
cacheChunkCount: 0
};
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
};
/**
* Set the data to be cached
* @returns
*/
export const setCacheData = (data: ICacheData) => {
!isExists && fs.mkdirSync(dirPath);
fs.writeFileSync(filePath, JSON.stringify(data));
};
por último
Esta serie tendrá actualizaciones continuas. En cuanto a la columna completa «Vite From Beginner to Mastery», la explicaré principalmente desde los siguientes aspectos: ¡esté atento!
Estimados, ya lo han visto todo aquí, ¿por qué no dejan su me gusta?👍.markdown-body pre,.markdown-body pre>code.hljs{color:#333;background:#f8f8f8}.hljs-comment,.hljs- quote{color:#998;font-style:italic}.hljs-keyword,.hljs-selector-tag,.hljs-subst{color:#333;font-weight:700}.hljs-literal,.hljs-number ,.hljs-tag .hljs-attr,.hljs-template-variable,.hljs-variable{color:teal}.hljs-doctag,.hljs-string{color:#d14}.hljs-section,.hljs-selector -id,.hljs-title{color:#900;font-weight:700}.hljs-subst{font-weight:400}.hljs-class .hljs-title,.hljs-type{color:#458;font -weight:700}.hljs-attribute,.hljs-name,.hljs-tag{color:navy;font-weight:400}.hljs-link,.hljs-regexp{color:#009926}.hljs-bullet, .hljs-symbol{color:#990073}.hljs-built_in,.hljs-builtin-name{color:#0086b3}.hljs-meta{color:#999;font-weight:700}.hljs-deletion{background: #fdd}.hljs-addition{background:#dfd}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700} Categoría: Front-end Etiquetas: Front-end Vite Los artículos se incluyen en la columna:
Vite from entry to mastery
Vite (se pronuncia de forma similar a [weɪt], que significa ligero) es una herramienta de construcción front-end para el desarrollo web impulsada por ES Module nativo.
Tiene las siguientes características:
💡 Arranque del servicio extremadamente rápido;
⚡️ Hot reload ligero y rápido;
🛠️ Funciones abundantes;
📦 Compilación optimizada;
🔩 Complemento universal;
🔑 API totalmente tipada.
Artículos relacionados
-
6 tecnologías opcionales para el almacenamiento de datos
Equipo editorial
Ver más ofertas especiales
-
Short Message Service (SMS) y servicio de correo
Paquete de 50,000 correos desde USD $1.99; 120 mensajes cortos desde USD $1.00
