@varlinor/builder-vue3
Version:
This package provides a set of Rollup and Vite configurations and utility functions tailored for Vue.js development environments, focusing on simplifying the build process for front-end development. It includes modules for configuring Rollup and Vite for
218 lines (215 loc) • 7.17 kB
JavaScript
import fs from 'fs-extra';
import path from 'path';
import { normalizePath, scanFilesByConditions, loadJsonFile, getAllDependencies } from '@varlinor/node-tools';
import { build } from 'unbuild';
import { defineConfig, build as build$1 } from 'vite';
import vue from '@vitejs/plugin-vue';
import replacePlugin from '@rollup/plugin-replace';
import postcssPresetEnv from 'postcss-preset-env';
import cssInject from 'vite-plugin-css-injected-by-js';
import { merge, uniq } from 'lodash-es';
function getSfcBuildConfig(opts) {
const { input, name, externals, output, plugins, replace, hooks } = opts;
if (!input || !name) return null;
const pluginArr = [...plugins, vue()];
if (!!replace) {
pluginArr.push(
replacePlugin({
preventAssingment: true,
// 避免破坏赋值操作。
values: replace
// 待替换的隐射
})
);
}
return defineConfig({
configFile: false,
plugins: [...pluginArr, cssInject()],
css: {
preprocessorOptions: { css: { charset: false } },
postcss: {
plugins: [postcssPresetEnv()]
}
},
build: {
minify: false,
cssMinify: true,
emptyOutDir: false,
lib: {
name,
formats: ["es"],
entry: input,
filename: `${name}.js`
},
rollupOptions: {
external: Array.isArray(externals) && externals.length ? [...externals] : [],
output
}
}
});
}
function getScriptBuildConfig(opts) {
if (!opts.entries || !opts.externals) {
throw new Error("entries or externals is empty, please check!");
}
const { entries, externals, clean, rollup, alias, replace, hooks } = opts;
const buildOpt = merge(
{
failOnWarn: false,
clean: true,
declaration: false,
rollup: {
emitCJS: false,
output: {
format: "es",
// 设置输出格式为 ES 模块
entryFileNames: "[name].js"
// 设置输出文件名为 .js 后缀
}
}
},
{
entries,
externals,
clean,
rollup,
alias: alias || {},
replace: replace || {},
hooks
// unbuild 提供的hooks
}
);
return buildOpt;
}
async function buildScripts(packageRoot, packOption) {
const rootDir = normalizePath(path.resolve(process.cwd(), packageRoot || "."));
const externals = checkAndLoadExternals(rootDir, packOption.externals);
const jsBuildOpt = getScriptBuildConfig({
entries: packOption.entries,
// 所有的sfc的包含install的文件位置
clean: packOption.clean,
externals,
replace: packOption.replace || {},
alias: packOption.alias || {},
hooks: packOption.hooks || {}
});
console.log("Ready to build script files ...");
await build(null, false, jsBuildOpt);
copyStaticResources(rootDir, packOption.staticResources);
console.log("Build script files successfully!");
}
function copyStaticResources(packageRoot, staticResources) {
if (!!staticResources && staticResources.length) {
staticResources.forEach(({ src, dest }) => {
const targetSrc = path.join(packageRoot, src);
const targetDest = path.join(packageRoot, "dist", dest);
if (fs.existsSync(targetSrc)) {
console.log("copy [%s] to [dist/%s]!", targetSrc, targetDest);
fs.copySync(targetSrc, targetDest);
}
});
}
}
async function buildPackage(packageRoot, packOption) {
const rootDir = normalizePath(path.resolve(process.cwd(), packageRoot || "."));
const ComponentsInfo = checkAndLoadComDefs(rootDir);
const allExternals = checkAndLoadExternals(rootDir, packOption.externals);
const extraPlugins = packOption.plugins || [];
const DistDir = `${rootDir}/dist`;
const buildPromise = [];
ComponentsInfo.forEach((com) => {
const { packageName, basedir, filename, outputPath, outputFileName } = com;
const outDir = outputPath.substring("/src".length, outputPath.length);
const entryFileName = filename === "index.vue" ? filename : outputFileName === "index" ? "index" : `index-${outputFileName}`;
const entry = path.join("./", outputPath, entryFileName);
const outputBase = `${DistDir}/${outDir}`;
const comOutPath = `${outDir}/${outputFileName}`;
const buildOpt = getSfcBuildConfig({
input: entry,
output: {
dir: outputBase,
entryFileNames: `${outputFileName}.js`
},
name: comOutPath,
externals: allExternals,
plugins: extraPlugins,
replace: packOption.replace
});
if (buildOpt) {
buildPromise.push(build$1(buildOpt));
}
});
console.log("Ready to build Vue SFC ...");
await Promise.all(buildPromise);
console.log("Build Vue SFC files successfully!");
if (packOption.entries) {
const entries = [];
entries.push(...packOption.entries);
await buildScripts(packageRoot, {
entries,
externals: allExternals,
clean: false,
replace: packOption.replace,
hooks: packOption.hooks
});
}
copyStaticResources(packageRoot, packOption.staticResources);
}
function getI18nFiles(packageRoot) {
function filterFunc(f, filePath, parentPath) {
return parentPath.indexOf("node_modules") < 0 && parentPath.endsWith("i18n");
}
return getScriptFiles(packageRoot, filterFunc);
}
function getScriptFiles(packageRoot, entryFilter) {
function modifier(file, filePath, parentPath) {
let name = path.basename(filePath, ".ts");
let parentP = normalizePath(parentPath);
if (!parentP.endsWith("/")) {
parentP += "/";
}
const srcIndex = parentP.indexOf("src/");
let pPath = parentP;
if (srcIndex !== -1) {
pPath = parentP.slice(srcIndex + "src/".length);
}
if (pPath.indexOf("./") === 0) {
pPath = pPath.substring(2);
}
name = pPath ? `${pPath}${name}` : name;
return {
name,
input: normalizePath(filePath)
};
}
function filterFunc(f, filePath, parentPath) {
if (entryFilter != null && typeof entryFilter == "function") {
return filePath.endsWith(".ts") && entryFilter(f, filePath, parentPath);
} else {
return filePath.endsWith(".ts");
}
}
return scanFilesByConditions(packageRoot, modifier, filterFunc);
}
function checkAndLoadComDefs(rootDir) {
const comDefPath = path.join(rootDir, "./components.json");
if (!fs.existsSync(comDefPath)) {
throw new Error(`Cannot find components.json in dir [${rootDir}]`);
}
return loadJsonFile(comDefPath);
}
function checkAndLoadExternals(rootDir, extraExternals) {
const pkgPath = path.join(rootDir, "./package.json");
if (!fs.existsSync(pkgPath)) {
throw new Error(`Cannot find package.json in dir [${rootDir}]`);
}
const { dependencies, devDependencies } = loadJsonFile(pkgPath);
const externals = getAllDependencies(dependencies);
const devExternals = getAllDependencies(devDependencies);
let allExternals = [...externals, ...devExternals];
if (extraExternals) {
allExternals = uniq([...allExternals, ...extraExternals]);
}
return allExternals;
}
export { buildPackage, buildScripts, getI18nFiles, getScriptBuildConfig, getScriptFiles, getSfcBuildConfig };