build!: simplify build & support native esm import (#3900)

* build: refactor build

* refactor: reorganize files

* refactor: refactor build

* build: improve perf

* fix: scripts

* build: add rollup-plugin-filesize

* chore: scripts ignore no-console

* build: disable tree-shaking

* build: improve code

* build: add sourcemap

* build: add banner

* refactor: remove annotation
This commit is contained in:
三咲智子 2021-10-18 14:45:57 +08:00 committed by GitHub
parent 3e2be8eb0b
commit fb94222bb4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
41 changed files with 250 additions and 616 deletions

View File

@ -1,5 +1,6 @@
import path from 'path'
import { epOutput } from './utils/paths'
import { EP_PKG } from './utils/constants'
import type { ModuleFormat } from 'rollup'
export const modules = ['esm', 'cjs'] as const
@ -29,7 +30,7 @@ export const buildConfig: Record<Module, BuildInfo> = {
path: path.resolve(epOutput, 'es'),
},
bundle: {
path: 'element-plus/es',
path: `${EP_PKG}/es`,
},
},
cjs: {
@ -40,9 +41,13 @@ export const buildConfig: Record<Module, BuildInfo> = {
path: path.resolve(epOutput, 'lib'),
},
bundle: {
path: 'element-plus/lib',
path: `${EP_PKG}/lib`,
},
},
}
export const buildConfigEntries = Object.entries(
buildConfig
) as BuildConfigEntries
export type BuildConfig = typeof buildConfig
export type BuildConfigEntries = [Module, BuildInfo][]

View File

@ -1,122 +0,0 @@
import fs from 'fs'
import path from 'path'
import { series, parallel } from 'gulp'
import { rollup } from 'rollup'
import vue from 'rollup-plugin-vue'
import css from 'rollup-plugin-css-only'
import { nodeResolve } from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'
import esbuild from 'rollup-plugin-esbuild'
import { sync as globSync } from 'fast-glob'
import filesize from 'rollup-plugin-filesize'
import { compRoot, buildOutput } from './utils/paths'
import {
generateExternal,
rollupPathRewriter,
writeBundles,
} from './utils/rollup'
import { run } from './utils/process'
import { withTaskName } from './utils/gulp'
import { genComponentTypes } from './component-types'
import { buildConfig } from './info'
import reporter from './size-reporter'
import type { OutputOptions } from 'rollup'
import type { Module, BuildConfigEntries } from './info'
const plugins = [
css(),
vue({
target: 'browser',
// css: false,
}),
nodeResolve(),
commonjs(),
esbuild(),
]
async function getComponents() {
const files = globSync('*', {
cwd: compRoot,
onlyDirectories: true,
})
return files.map((file) => ({
path: path.resolve(compRoot, file),
name: file,
}))
}
export async function buildEachComponent() {
const componentPaths = await getComponents()
const external = await generateExternal({ full: false })
const pathRewriter = await rollupPathRewriter()
const builds = componentPaths.map(
async ({ path: p, name: componentName }) => {
const entry = path.resolve(p, 'index.ts')
if (!fs.existsSync(entry)) return
const rollupConfig = {
input: entry,
plugins,
external,
}
const opts = (Object.entries(buildConfig) as BuildConfigEntries).map(
([module, config]): OutputOptions => ({
format: config.format,
file: path.resolve(
config.output.path,
'components',
componentName,
'index.js'
),
exports: module === 'cjs' ? 'named' : undefined,
paths: pathRewriter(module),
plugins: [filesize({ reporter })],
})
)
const bundle = await rollup(rollupConfig)
await writeBundles(bundle, opts)
}
)
await Promise.all(builds)
}
export async function buildComponentEntry() {
const entry = path.resolve(compRoot, 'index.ts')
const config = {
input: entry,
plugins,
external: () => true,
}
const opts = Object.values(buildConfig).map(
(config): OutputOptions => ({
format: config.format,
file: path.resolve(config.output.path, 'components/index.js'),
plugins: [filesize({ reporter })],
})
)
const bundle = await rollup(config)
await writeBundles(bundle, opts)
}
function copyTypes() {
const src = `${buildOutput}/types/components/`
const copy = (module: Module) =>
withTaskName(`copyTypes:${module}`, () =>
run(`rsync -a ${src} ${buildConfig[module].output.path}/components/`)
)
return parallel(copy('esm'), copy('cjs'))
}
export const buildComponent = series(
parallel(genComponentTypes, buildEachComponent, buildComponentEntry),
copyTypes()
)
export { genComponentTypes }

View File

@ -1,82 +0,0 @@
import path from 'path'
import fs from 'fs/promises'
import { bold } from 'chalk'
import glob from 'fast-glob'
import { Project, ScriptTarget, ModuleKind } from 'ts-morph'
import { parallel } from 'gulp'
import { epRoot, buildOutput, projRoot } from './utils/paths'
import { yellow, green } from './utils/log'
import { buildConfig } from './info'
import { withTaskName } from './utils/gulp'
import { run } from './utils/process'
import type { Module } from './info'
import type { SourceFile } from 'ts-morph'
const TSCONFIG_PATH = path.resolve(projRoot, 'tsconfig.json')
export const genEntryTypes = async () => {
const files = await glob('*.ts', {
cwd: epRoot,
absolute: true,
onlyFiles: true,
})
const project = new Project({
compilerOptions: {
module: ModuleKind.ESNext,
allowJs: true,
emitDeclarationOnly: true,
noEmitOnError: false,
outDir: path.resolve(buildOutput, 'entry/types'),
target: ScriptTarget.ESNext,
rootDir: epRoot,
strict: false,
},
skipFileDependencyResolution: true,
tsConfigFilePath: TSCONFIG_PATH,
skipAddingFilesFromTsConfig: true,
})
const sourceFiles: SourceFile[] = []
files.map((f) => {
const sourceFile = project.addSourceFileAtPath(f)
sourceFiles.push(sourceFile)
})
project.addSourceFilesAtPaths(path.resolve(projRoot, 'typings', '*.d.ts'))
const diagnostics = project.getPreEmitDiagnostics()
console.log(project.formatDiagnosticsWithColorAndContext(diagnostics))
await project.emit({
emitOnlyDtsFiles: true,
})
const tasks = sourceFiles.map(async (sourceFile) => {
yellow(`Emitting file: ${bold(sourceFile.getFilePath())}`)
const emitOutput = sourceFile.getEmitOutput()
for (const outputFile of emitOutput.getOutputFiles()) {
const filepath = outputFile.getFilePath()
await fs.mkdir(path.dirname(filepath), { recursive: true })
await fs.writeFile(
filepath,
outputFile.getText().replaceAll('@element-plus', '.'),
'utf8'
)
green(`Definition for file: ${bold(sourceFile.getBaseName())} generated`)
}
})
await Promise.all(tasks)
}
export const copyEntryTypes = (() => {
const src = path.resolve(buildOutput, 'entry/types')
const copy = (module: Module) =>
withTaskName(`copyEntryTypes:${module}`, () =>
run(`rsync -a ${src}/ ${buildConfig[module].output.path}/`)
)
return parallel(copy('esm'), copy('cjs'))
})()

View File

@ -1,64 +1,39 @@
import path from 'path'
import fs from 'fs'
import { nodeResolve } from '@rollup/plugin-node-resolve'
import { rollup } from 'rollup'
import commonjs from '@rollup/plugin-commonjs'
import vue from 'rollup-plugin-vue'
import esbuild from 'rollup-plugin-esbuild'
import replace from '@rollup/plugin-replace'
import filesize from 'rollup-plugin-filesize'
import { parallel } from 'gulp'
import { genEntryTypes } from './entry-types'
import { RollupResolveEntryPlugin } from './rollup-plugin-entry'
import { version } from '../packages/element-plus/version'
import { RollupResolveEntryPlugin } from './plugins/rollup-plugin-entry'
import { epRoot, epOutput } from './utils/paths'
import { yellow, green } from './utils/log'
import {
generateExternal,
rollupPathRewriter,
writeBundles,
} from './utils/rollup'
import { buildConfig } from './info'
import { run } from './utils/process'
import { generateExternal, writeBundles } from './utils/rollup'
import { withTaskName } from './utils/gulp'
import type { BuildConfigEntries } from './info'
import type { RollupOptions, OutputOptions, InputOptions } from 'rollup'
const getConfig = async (
opt: {
minify?: boolean
sourceMap?: boolean
plugins?: InputOptions['plugins']
} = {}
): Promise<RollupOptions> => ({
input: path.resolve(epRoot, 'index.ts'),
plugins: [
nodeResolve(),
vue({
target: 'browser',
// css: false,
exposeFilename: false,
}),
commonjs(),
esbuild({
minify: opt.minify,
sourceMap: opt.sourceMap,
}),
replace({
'process.env.NODE_ENV': JSON.stringify('production'),
}),
...(opt.plugins ?? []),
],
external: await generateExternal({ full: true }),
})
export const buildFull = (minify: boolean) => async () => {
const bundle = await rollup(
await getConfig({
plugins: [RollupResolveEntryPlugin()],
minify,
sourceMap: minify,
})
)
const bundle = await rollup({
input: path.resolve(epRoot, 'index.ts'),
plugins: [
nodeResolve(),
vue({
target: 'browser',
exposeFilename: false,
}),
commonjs(),
esbuild({ minify, sourceMap: minify }),
replace({
'process.env.NODE_ENV': JSON.stringify('production'),
}),
await RollupResolveEntryPlugin(),
filesize(),
],
external: await generateExternal({ full: true }),
})
const banner = `/*! Element Plus v${version} */\n`
await writeBundles(bundle, [
{
format: 'umd',
@ -69,6 +44,7 @@ export const buildFull = (minify: boolean) => async () => {
vue: 'Vue',
},
sourcemap: minify,
banner,
},
{
format: 'esm',
@ -77,51 +53,12 @@ export const buildFull = (minify: boolean) => async () => {
`dist/index.full${minify ? '.min' : ''}.mjs`
),
sourcemap: minify,
banner,
},
])
}
export const buildEntry = async () => {
const entryFiles = await fs.promises.readdir(epRoot, {
withFileTypes: true,
})
const entryPoints = entryFiles
.filter((f) => f.isFile())
.filter((f) => !['package.json', 'README.md'].includes(f.name))
.map((f) => path.resolve(epRoot, f.name))
const bundle = await rollup({
...(await getConfig()),
input: entryPoints,
external: () => true,
})
yellow('Generating entries')
const rewriter = await rollupPathRewriter()
writeBundles(
bundle,
(Object.entries(buildConfig) as BuildConfigEntries).map(
([module, config]): OutputOptions => ({
format: config.format,
dir: config.output.path,
exports: config.format === 'cjs' ? 'named' : undefined,
paths: rewriter(module),
})
)
)
green('entries generated')
}
export const copyFullStyle = () =>
Promise.all([
run(`cp ${epOutput}/theme-chalk/index.css ${epOutput}/dist/index.css`),
run(`cp -R ${epOutput}/theme-chalk/fonts ${epOutput}/dist/fonts`),
])
export const buildFullBundle = parallel(
withTaskName('buildFullMinified', buildFull(true)),
withTaskName('buildFull', buildFull(false)),
buildEntry,
genEntryTypes
withTaskName('buildFull', buildFull(false))
)

View File

@ -1,54 +1,66 @@
import path from 'path'
import { series, parallel } from 'gulp'
import { copyStyle } from './style'
import { copyEntryTypes } from './entry-types'
import { run } from './utils/process'
import { withTaskName } from './utils/gulp'
import { epOutput, epPackage, projRoot } from './utils/paths'
import { copyFullStyle } from './full-bundle'
import { buildOutput, epOutput, epPackage, projRoot } from './utils/paths'
import { buildConfig } from './build-info'
import type { TaskFunction } from 'gulp'
import type { Module } from './build-info'
const runTask = (name: string) =>
withTaskName(name, () => run(`pnpm run build ${name}`))
export const copySourceCode = async () => {
await run(`cp -R packages ${epOutput}`)
await run(`cp ${epPackage} ${epOutput}/package.json`)
export const copyFiles = () => {
const copyTypings = async () => {
const src = path.resolve(projRoot, 'typings', 'global.d.ts')
await run(`cp ${src} ${epOutput}`)
}
return Promise.all([
run(`cp ${epPackage} ${path.join(epOutput, 'package.json')}`),
run(`cp README.md ${epOutput}`),
copyTypings(),
])
}
export const copyREADME = async () => {
await run(`cp README.md ${epOutput}`)
export const copyTypesDefinitions: TaskFunction = (done) => {
const src = `${buildOutput}/types/`
const copy = (module: Module) =>
withTaskName(`copyTypes:${module}`, () =>
run(`rsync -a ${src} ${buildConfig[module].output.path}/`)
)
return parallel(copy('esm'), copy('cjs'))(done)
}
export const copyDefinitions = async () => {
const files = [path.resolve(projRoot, 'typings', 'global.d.ts')]
await run(`cp ${files.join(' ')} ${epOutput}`)
export const copyFullStyle = async () => {
await run(`mkdir -p ${epOutput}/dist/fonts`)
await Promise.all([
run(`cp ${epOutput}/theme-chalk/index.css ${epOutput}/dist/index.css`),
run(`cp -R ${epOutput}/theme-chalk/fonts ${epOutput}/dist/fonts`),
])
}
export default series(
withTaskName('clean', () => run('pnpm run clean')),
parallel(
runTask('buildComponent'),
runTask('buildStyle'),
runTask('buildModules'),
runTask('buildFullBundle'),
runTask('generateTypesDefinitions'),
runTask('buildHelper'),
withTaskName('buildEachPackages', () =>
run('pnpm run --filter ./packages --parallel --stream build')
series(
withTaskName('buildThemeChalk', () =>
run('pnpm run -C packages/theme-chalk build')
),
copyFullStyle
)
),
parallel(
copyStyle(),
copyFullStyle,
copyEntryTypes,
copySourceCode,
copyREADME,
copyDefinitions
)
parallel(copyTypesDefinitions, copyFiles)
)
export * from './component'
export * from './style'
export * from './types-definitions'
export * from './modules'
export * from './full-bundle'
export * from './entry-types'
export * from './helper'

54
build/modules.ts Normal file
View File

@ -0,0 +1,54 @@
import { rollup } from 'rollup'
import vue from 'rollup-plugin-vue'
import css from 'rollup-plugin-css-only'
import { nodeResolve } from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'
import esbuild from 'rollup-plugin-esbuild'
import filesize from 'rollup-plugin-filesize'
import glob from 'fast-glob'
import { epRoot, pkgRoot } from './utils/paths'
import { RollupResolveEntryPlugin } from './plugins/rollup-plugin-entry'
import { generateExternal, writeBundles } from './utils/rollup'
import { excludeFiles } from './utils/pkg'
import { reporter } from './plugins/size-reporter'
import { buildConfigEntries } from './build-info'
import type { OutputOptions } from 'rollup'
export const buildModules = async () => {
const input = excludeFiles(
await glob('**/*.{js,ts,vue}', {
cwd: pkgRoot,
absolute: true,
onlyFiles: true,
})
)
const bundle = await rollup({
input,
plugins: [
await RollupResolveEntryPlugin(),
css(),
vue({ target: 'browser' }),
nodeResolve(),
commonjs(),
esbuild({
sourceMap: true,
}),
filesize({ reporter }),
],
external: await generateExternal({ full: false }),
treeshake: false,
})
await writeBundles(
bundle,
buildConfigEntries.map(([module, config]): OutputOptions => {
return {
format: config.format,
dir: config.output.path,
exports: module === 'cjs' ? 'named' : undefined,
preserveModules: true,
preserveModulesRoot: epRoot,
sourcemap: true,
}
})
)
}

View File

@ -1,54 +0,0 @@
import path from 'path'
import ts from 'gulp-typescript'
import { src, dest, series, parallel } from 'gulp'
import { withTaskName, gulpPathRewriter } from './utils/gulp'
import { buildConfig } from './info'
import { epOutput, projRoot } from './utils/paths'
import { getPackageManifest } from './utils/pkg'
import { EP_PREFIX } from './constants'
import type { BuildConfigEntries } from './info'
export const buildPackage = (pkgPath: string) => {
const manifest = getPackageManifest(path.resolve(pkgPath, 'package.json'))
const pkgName = manifest.name!.replace(`${EP_PREFIX}/`, '')
const tasks = (Object.entries(buildConfig) as BuildConfigEntries).map(
([module, config]) => {
const output = path.resolve(pkgPath, 'dist', config.output.name)
const build = () => {
const tsConfig = path.resolve(projRoot, 'tsconfig.json')
const inputs = [
'**/*.ts',
'!node_modules',
'!gulpfile.ts',
'!__test?(s)__/*',
'!test?(s)/*',
path.resolve(projRoot, 'typings', '*.d.ts'),
]
return withTaskName(`build:${pkgName}:${module}`, () =>
src(inputs)
.pipe(
ts.createProject(tsConfig, {
module: config.module,
strict: false,
})()
)
.pipe(gulpPathRewriter(module))
.pipe(dest(output))
)
}
const copy = () =>
withTaskName(`copy:${pkgName}:${module}`, () =>
src(`${output}/**`).pipe(
dest(path.resolve(epOutput, config.output.name, pkgName))
)
)
return series(build(), copy())
}
)
return parallel(...tasks)
}

View File

@ -0,0 +1,32 @@
import path from 'path'
import { pkgRoot } from '../utils/paths'
import { EP_PKG, EP_PREFIX } from '../utils/constants'
import { getWorkspaceNames } from '../utils/pkg'
import type { Plugin } from 'rollup'
export async function RollupResolveEntryPlugin(): Promise<Plugin> {
const pkgs = (await getWorkspaceNames(pkgRoot))
.filter((pkg) => pkg.startsWith(`${EP_PREFIX}/`))
.map((pkg) => pkg.replace(`${EP_PREFIX}/`, ''))
return {
name: 'element-plus-entry-plugin',
transform(code, id) {
if (id.includes('packages')) {
code = code.replaceAll(
`${EP_PREFIX}/theme-chalk`,
`${EP_PKG}/theme-chalk`
)
code = code.replace(
new RegExp(`@element-plus\\/(${pkgs.join('|')})`, 'g'),
`${path.relative(path.dirname(id), path.resolve(pkgRoot))}/$1`
)
return {
code,
map: null,
}
}
},
}
}

View File

@ -0,0 +1,9 @@
import { cyan, bold, yellow, green } from 'chalk'
import type { FileSizeReporter } from 'rollup-plugin-filesize'
export const reporter: FileSizeReporter = (opt, outputOptions, info) => {
return `${cyan(bold(info.fileName))}: bundle size ${yellow(
info.bundleSize
)} -> minified ${green(info.minSize)}`
}

View File

@ -1,23 +0,0 @@
import path from 'path'
import type { Plugin } from 'rollup'
export function RollupResolveEntryPlugin(): Plugin {
return {
name: 'element-plus-entry-plugin',
transform(code, id) {
if (id.includes('packages')) {
return {
code: code.replace(
/@element-plus\/(components|directives|utils|hooks|tokens|locale)/g,
`${path.relative(
path.dirname(id),
path.resolve(__dirname, '../packages')
)}/$1`
),
map: null,
}
}
return { code, map: null }
},
}
}

View File

@ -1,18 +0,0 @@
import { cyan, bold, yellow, green } from 'chalk'
import type { FileSizeReporter } from 'rollup-plugin-filesize'
const reporter: FileSizeReporter = (opt, outputOptions, info) => {
const values = [
info.fileName ? [`${outputOptions.file?.split('packages/').pop()}`] : [],
[`${info.bundleSize}`],
...(info.minSize ? [`${info.minSize}`] : []),
]
return `${cyan(bold(values[0]))}: bundle size ${yellow(
values[1]
)} -> minified ${green(values[2])}`
}
export default reporter

View File

@ -1,44 +0,0 @@
import path from 'path'
import { parallel, dest, src } from 'gulp'
import ts from 'gulp-typescript'
import { buildOutput, compRoot } from './utils/paths'
import { buildConfig } from './info'
import { withTaskName, gulpPathRewriter } from './utils/gulp'
import { run } from './utils/process'
import type { Module } from './info'
const inputs = path.resolve(compRoot, '**/style/*.ts')
const output = path.resolve(buildOutput, 'styles')
const tsProject = (module: Module) =>
ts.createProject('tsconfig.json', {
declaration: true,
target: 'ESNext',
skipLibCheck: true,
module: buildConfig[module].module,
})()
const build = (module: Module) =>
withTaskName(`buildStyle:${module}`, () =>
src(inputs)
.pipe(gulpPathRewriter(module))
.pipe(tsProject(module))
.pipe(dest(path.resolve(output, buildConfig[module].output.name)))
)
export const buildStyle = parallel(build('esm'), build('cjs'))
export const copyStyle = () => {
const copy = (module: Module) => {
const config = buildConfig[module]
const src = path.resolve(buildOutput, 'styles', config.output.name)
const dst = path.resolve(config.output.path, 'components')
return withTaskName(`copyStyle:${module}`, () =>
run(`rsync -a ${src}/ ${dst}/`)
)
}
return parallel(copy('esm'), copy('cjs'))
}

View File

@ -6,9 +6,10 @@ import glob from 'fast-glob'
import { bold } from 'chalk'
import { green, red, yellow } from './utils/log'
import { buildOutput, compRoot, projRoot } from './utils/paths'
import { buildOutput, pkgRoot, projRoot } from './utils/paths'
import { pathRewriter } from './utils/pkg'
import { excludeFiles, pathRewriter } from './utils/pkg'
import { run } from './utils/process'
import type { SourceFile } from 'ts-morph'
const TSCONFIG_PATH = path.resolve(projRoot, 'tsconfig.json')
@ -17,7 +18,7 @@ const outDir = path.resolve(buildOutput, 'types')
/**
* fork = require( https://github.com/egoist/vue-dts-gen/blob/main/src/index.ts
*/
export const genComponentTypes = async () => {
export const generateTypesDefinitions = async () => {
const project = new Project({
compilerOptions: {
allowJs: true,
@ -35,27 +36,12 @@ export const genComponentTypes = async () => {
skipAddingFilesFromTsConfig: true,
})
const excludedFiles = [
/\/demo\/\w+\.vue$/,
'mock',
'package.json',
'spec',
'test',
'css',
'.DS_Store',
'node_modules',
]
const filePaths = (
await glob('**/*', {
cwd: compRoot,
onlyFiles: true,
const filePaths = excludeFiles(
await glob('**/*.{js,ts,vue}', {
cwd: pkgRoot,
absolute: true,
onlyFiles: true,
})
).filter(
(path) =>
!excludedFiles.some((f) =>
f instanceof RegExp ? f.test(path) : path.includes(f)
)
)
const sourceFiles: SourceFile[] = []
@ -93,7 +79,6 @@ export const genComponentTypes = async () => {
)
const diagnostics = project.getPreEmitDiagnostics()
console.log(project.formatDiagnosticsWithColorAndContext(diagnostics))
await project.emit({
@ -101,7 +86,7 @@ export const genComponentTypes = async () => {
})
const tasks = sourceFiles.map(async (sourceFile) => {
const relativePath = path.relative(compRoot, sourceFile.getFilePath())
const relativePath = path.relative(pkgRoot, sourceFile.getFilePath())
yellow(`Generating definition for file: ${bold(relativePath)}`)
const emitOutput = sourceFile.getEmitOutput()
@ -119,14 +104,22 @@ export const genComponentTypes = async () => {
await fs.writeFile(
filepath,
pathRewriter('esm', true)(outputFile.getText()),
pathRewriter('esm')(outputFile.getText()),
'utf8'
)
green(`Definition for file: ${bold(relativePath)} generated`)
})
await Promise.all(tasks)
})
await Promise.all(tasks)
const epFiles = await glob('**/*', {
cwd: path.resolve(outDir, 'element-plus'),
absolute: true,
})
await run(`mv ${epFiles.join(' ')} ${outDir}`)
await run(`rmdir ${path.resolve(outDir, 'element-plus')}`)
}

View File

@ -1 +1,2 @@
export const EP_PREFIX = '@element-plus'
export const EP_PKG = 'element-plus'

View File

@ -1,17 +1,4 @@
import through2 from 'through2'
import { pathRewriter } from './pkg'
import type { TaskFunction } from 'gulp'
import type { Module } from '../info'
export const withTaskName = <T extends TaskFunction>(name: string, fn: T) =>
Object.assign(fn, { displayName: name })
export const gulpPathRewriter = (module: Module) => {
const rewriter = pathRewriter(module, true)
return through2.obj((file, _, cb) => {
const contents: string = file.contents.toString()
file.contents = Buffer.from(rewriter(contents))
cb(null, file)
})
}

View File

@ -4,6 +4,7 @@ import chalk from 'chalk'
export function cyan(str: string) {
console.log(chalk.cyan(str))
}
export function yellow(str: string) {
console.log(chalk.yellow(str))
}

View File

@ -1,24 +1,18 @@
import findWorkspacePackages from '@pnpm/find-workspace-packages'
import { buildConfig } from '../info'
import { EP_PREFIX } from '../constants'
import { buildConfig } from '../build-info'
import { EP_PREFIX } from './constants'
import { projRoot } from './paths'
import type { Module } from '../info'
import type { Module } from '../build-info'
import type { ProjectManifest } from '@pnpm/types'
export const getWorkspacePackages = () => findWorkspacePackages(projRoot)
export const getWorkspaceNames = async () => {
export const getWorkspaceNames = async (dir = projRoot) => {
const pkgs = await findWorkspacePackages(projRoot)
return pkgs
.filter((pkg) => pkg.dir.startsWith(dir))
.map((pkg) => pkg.manifest.name)
.filter((name): name is string => !!name)
}
export const getWorkspacePackageManifest = async (
name: string
): Promise<ProjectManifest> => {
const packages = await getWorkspacePackages()
const { manifest } = packages.find((pkg) => pkg.manifest.name === name)!
return manifest
}
export const getPackageManifest = (pkgPath: string) => {
// eslint-disable-next-line @typescript-eslint/no-var-requires
@ -31,13 +25,19 @@ export const getPackageDependencies = (pkgPath: string): string[] => {
return Object.keys(dependencies ?? {})
}
export const pathRewriter = (module: Module, replaceAll: boolean) => {
const replaceName = replaceAll ? 'replaceAll' : 'replace'
export const pathRewriter = (module: Module) => {
const config = buildConfig[module]
return (id: string) => {
id = id[replaceName](`${EP_PREFIX}/theme-chalk`, 'element-plus/theme-chalk')
id = id[replaceName](`${EP_PREFIX}/`, `${config.bundle.path}/`)
id = id.replaceAll(`${EP_PREFIX}/theme-chalk`, 'element-plus/theme-chalk')
id = id.replaceAll(`${EP_PREFIX}/`, `${config.bundle.path}/`)
return id
}
}
export const excludeFiles = (files: string[]) => {
const excludes = ['node_modules', 'test', 'mock', 'gulpfile', 'dist']
return files.filter(
(path) => !excludes.some((exclude) => path.includes(exclude))
)
}

View File

@ -1,13 +1,11 @@
import { spawn } from 'child_process'
import { green } from './log'
import { green } from 'chalk'
import { projRoot } from './paths'
export const run = async (command: string, cwd: string = projRoot) =>
new Promise<void>((resolve, reject) => {
const args = command.split(' ')
const cmd = args.shift()!
green(`run: ${cmd} ${args.join(' ')}`)
const [cmd, ...args] = command.split(' ')
console.log(`run: ${green(`${cmd} ${args.join(' ')}`)}`)
const app = spawn(cmd, args, {
cwd,
stdio: 'inherit',

View File

@ -1,26 +1,15 @@
import { EP_PREFIX } from '../constants'
import { epPackage } from './paths'
import {
getWorkspacePackages,
getPackageDependencies,
getWorkspaceNames,
pathRewriter,
} from './pkg'
import type { Module } from '../info'
import { getPackageDependencies } from './pkg'
import type { OutputOptions, RollupBuild } from 'rollup'
export const generateExternal = async (options: { full: boolean }) => {
const monoPackages = (await getWorkspacePackages())
.map((pkg) => pkg.manifest.name)
// filter root package
.filter((name): name is string => !!name)
return (id: string) => {
const packages: string[] = ['vue']
if (!options.full) {
const depPackages = getPackageDependencies(epPackage)
packages.push('@vue', ...monoPackages, ...depPackages)
packages.push('element-plus/theme-chalk')
// dependencies
packages.push('@vue', ...getPackageDependencies(epPackage))
}
return [...new Set(packages)].some(
@ -32,21 +21,3 @@ export const generateExternal = async (options: { full: boolean }) => {
export function writeBundles(bundle: RollupBuild, options: OutputOptions[]) {
return Promise.all(options.map((option) => bundle.write(option)))
}
export const rollupPathRewriter = async () => {
const workspacePkgs = (await getWorkspaceNames()).filter((pkg) =>
pkg.startsWith(EP_PREFIX)
)
return (module: Module) => {
const rewriter = pathRewriter(module, false)
return (id: string) => {
if (workspacePkgs.some((pkg) => id.startsWith(pkg))) {
return rewriter(id)
} else {
return ''
}
}
}
}

View File

@ -1,22 +1,26 @@
import path from 'path'
import fs from 'fs'
import fs from 'fs/promises'
import chalk from 'chalk'
import { errorAndExit } from './utils/log'
import { errorAndExit } from '../../../build/utils/log'
import { docRoot } from '../utils/paths'
const credentialPlaceholder = 'API_TOKEN_PLACEHOLDER'
const CREDENTIAL = process.env.CROWDIN_TOKEN
if (!CREDENTIAL) {
errorAndExit(new Error('Environment variable CROWDIN_TOKEN cannot be empty'))
}
;(async () => {
console.info(chalk.cyan('Fetching Crowdin credential'))
const configPath = path.resolve(__dirname, '../docs/crowdin.yml')
const configPath = path.resolve(docRoot, 'crowdin.yml')
try {
const file = await fs.promises.readFile(configPath, {
const file = await fs.readFile(configPath, {
encoding: 'utf-8',
})
await fs.promises.writeFile(
await fs.writeFile(
configPath,
file.replace(credentialPlaceholder, CREDENTIAL!)
file.replace(credentialPlaceholder, CREDENTIAL)
)
console.info(chalk.green('Crowdin credential update successfully'))
} catch (e: any) {

View File

@ -3,6 +3,7 @@ import path from 'path'
import chalk from 'chalk'
import { docRoot } from '../utils/paths'
import { errorAndExit } from '../../../build/utils/log'
// NB: this file is only for generating files that enables developers to develop the website.
const componentLocaleRoot = path.resolve(docRoot, '.vitepress/crowdin')
@ -101,11 +102,10 @@ main()
.then(() => {
console.log(chalk.green('Locale for website development generated'))
})
.catch((e) => {
if (e.message === exists) {
.catch((err) => {
if (err.message === exists) {
// do nothing
} else {
console.log(chalk.red(e.message))
throw e
errorAndExit(err)
}
})

View File

@ -5,7 +5,8 @@
"dev": "pnpm gen-locale && vitepress dev .",
"build": "cross-env NODE_ENV=production && vitepress build .",
"serve": "cross-env NODE_ENV=production && vitepress serve .",
"gen-locale": "rimraf .vitepress/i18n && sucrase-node .vitepress/build/crowdin-generate.ts"
"gen-locale": "rimraf .vitepress/i18n && sucrase-node .vitepress/build/crowdin-generate.ts",
"crowdin-credentials": "sucrase-node .vitepress/build/crowdin-credentials.ts"
},
"dependencies": {
"@vueuse/core": "^6.5.3",

View File

@ -14,19 +14,19 @@
"test": "jest",
"dev": "pnpm -C play dev",
"gen": "bash ./scripts/gc.sh",
"gen:version": "sucrase-node build/gen-version.ts",
"update:version": "sucrase-node build/update-version.ts",
"gen:version": "sucrase-node scripts/gen-version.ts",
"update:version": "sucrase-node scripts/update-version.ts",
"clean": "pnpm run clean:lib && pnpm run clean -r --stream",
"clean:lib": "rimraf dist",
"build": "gulp -f build/gulpfile.ts",
"build": "gulp --require sucrase/register/ts -f build/gulpfile.ts",
"format": "prettier --write .",
"lint": "eslint . --ext .vue,.js,.ts,.jsx,.tsx --max-warnings 0 && pretty-quick --check --branch dev",
"lint:fix": "eslint --fix . --ext .vue,.js,.ts,.jsx,.tsx && pretty-quick --branch dev",
"docs:dev": "pnpm -C docs dev",
"docs:build": "pnpm -C docs build",
"docs:serve": "pnpm -C docs serve",
"docs:gen-locale": "pnpm -C docs gen-locale",
"docs:crowdin": "sucrase-node build/crowdin-credentials.ts",
"docs:dev": "pnpm run -C docs dev",
"docs:build": "pnpm run -C docs build",
"docs:serve": "pnpm run -C docs serve",
"docs:gen-locale": "pnpm run -C docs gen-locale",
"docs:crowdin-credentials": "pnpm run -C docs crowdin-credentials",
"prepare": "husky install",
"postinstall": "pnpm gen:version"
},

View File

@ -1,4 +1,3 @@
import { isBoolean } from '@vueuse/shared'
import { buildProps, definePropType, mutable } from '@element-plus/utils/props'
import type { ExtractPropTypes } from 'vue'
@ -41,7 +40,7 @@ export type ImageProps = ExtractPropTypes<typeof imageProps>
export const imageEmits = {
error: (evt: Event) => evt instanceof Event,
switch: (val: boolean) => isBoolean(val),
switch: (val: boolean) => typeof val === 'boolean',
close: () => true,
}
export type ImageEmits = typeof imageEmits

View File

@ -1,3 +0,0 @@
import { buildPackage } from '../../build/packages'
export default buildPackage(__dirname)

View File

@ -10,9 +10,5 @@
"peerDependencies": {
"vue": "^3.2.0"
},
"scripts": {
"clean": "rimraf dist",
"build": "gulp"
},
"gitHead": "c69724230befa8fede0e6b9c37fb0b7e39fd7cdd"
}

View File

@ -35,7 +35,8 @@
"vue": "^3.2.0"
},
"dependencies": {
"@popperjs/core": "^2.10.2",
"@element-plus/icons": "^0.0.11",
"@popperjs/core": "^2.10.1",
"@vueuse/core": "~6.1.0",
"async-validator": "^4.0.3",
"dayjs": "^1.10.7",

View File

@ -1,3 +0,0 @@
import { buildPackage } from '../../build/packages'
export default buildPackage(__dirname)

View File

@ -11,9 +11,5 @@
"peerDependencies": {
"vue": "^3.2.0"
},
"scripts": {
"clean": "rimraf dist",
"build": "gulp"
},
"gitHead": "c69724230befa8fede0e6b9c37fb0b7e39fd7cdd"
}

View File

@ -4,7 +4,7 @@ import { buildProps } from '@element-plus/utils/props'
import { useGlobalConfig } from '@element-plus/utils/util'
import type { ExtractPropTypes } from 'vue'
import type { MaybeRef } from '@vueuse/shared'
import type { MaybeRef } from '@vueuse/core'
const sizes = ['', 'large', 'medium', 'small', 'mini'] as const

View File

@ -1,3 +0,0 @@
import { buildPackage } from '../../build/packages'
export default buildPackage(__dirname)

View File

@ -8,9 +8,5 @@
"jsdelivr": "index.js",
"types": "index.d.ts",
"license": "MIT",
"scripts": {
"clean": "rimraf dist",
"build": "gulp"
},
"gitHead": "c69724230befa8fede0e6b9c37fb0b7e39fd7cdd"
}

View File

@ -8,7 +8,7 @@
"style": "index.css",
"scripts": {
"clean": "rimraf dist",
"build": "gulp"
"build": "gulp --require sucrase/register/ts"
},
"repository": {
"type": "git",

View File

@ -1,3 +0,0 @@
import { buildPackage } from '../../build/packages'
export default buildPackage(__dirname)

View File

@ -5,10 +5,6 @@
"peerDependencies": {
"vue": "^3.2.0"
},
"scripts": {
"clean": "rimraf dist",
"build": "gulp"
},
"main": "index.ts",
"module": "index.ts",
"types": "index.d.js",

View File

@ -1,3 +0,0 @@
import { buildPackage } from '../../build/packages'
export default buildPackage(__dirname)

View File

@ -5,9 +5,5 @@
"peerDependencies": {
"vue": "^3.2.0"
},
"scripts": {
"clean": "rimraf dist",
"build": "gulp"
},
"gitHead": "c69724230befa8fede0e6b9c37fb0b7e39fd7cdd"
}

4
pnpm-lock.yaml generated
View File

@ -188,7 +188,8 @@ importers:
packages/element-plus:
specifiers:
'@popperjs/core': ^2.10.2
'@element-plus/icons': ^0.0.11
'@popperjs/core': ^2.10.1
'@vueuse/core': ~6.1.0
async-validator: ^4.0.3
dayjs: ^1.10.7
@ -197,6 +198,7 @@ importers:
normalize-wheel-es: ^1.1.0
resize-observer-polyfill: ^1.5.1
dependencies:
'@element-plus/icons': 0.0.11
'@popperjs/core': 2.10.2
'@vueuse/core': 6.1.0_vue@3.2.20
async-validator: 4.0.3

5
scripts/.eslintrc.js Normal file
View File

@ -0,0 +1,5 @@
module.exports = {
rules: {
'no-console': 'off',
},
}

View File

@ -1,7 +1,7 @@
import fs from 'fs'
import { epPackage } from './utils/paths'
import { cyan, red, yellow, green } from './utils/log'
import { getPackageManifest } from './utils/pkg'
import { epPackage } from '../build/utils/paths'
import { cyan, red, yellow, green } from '../build/utils/log'
import { getPackageManifest } from '../build/utils/pkg'
const tagVersion = process.env.TAG_VERSION
const gitHead = process.env.GIT_HEAD