diff --git a/packages/vant-cli/src/commands/dev.ts b/packages/vant-cli/src/commands/dev.ts index b9699575f..e252d5ac9 100644 --- a/packages/vant-cli/src/commands/dev.ts +++ b/packages/vant-cli/src/commands/dev.ts @@ -6,6 +6,7 @@ import { siteDevConfig } from '../config/webpack.site.dev'; import { genPackageEntry } from '../compiler/gen-package-entry'; import { genMobileEntry } from '../compiler/gen-mobile-entry'; import { genDesktopEntry } from '../compiler/gen-desktop-entry'; +import { genStyleDepsMap } from '../compiler/gen-style-deps-map'; function runWebpack() { const server = new WebpackDevServer( @@ -34,6 +35,7 @@ function runWebpack() { export function dev() { clean(); + genStyleDepsMap(); genPackageEntry(); genMobileEntry(); genDesktopEntry(); diff --git a/packages/vant-cli/src/common/constant.ts b/packages/vant-cli/src/common/constant.ts index b969a4f73..c683ef21e 100644 --- a/packages/vant-cli/src/common/constant.ts +++ b/packages/vant-cli/src/common/constant.ts @@ -15,6 +15,7 @@ export const CONFIG_DIR = join(__dirname, '../config'); export const PACKAGE_ENTRY_FILE = join(DIST_DIR, 'package-entry.js'); export const MOBILE_ENTRY_FILE = join(DIST_DIR, 'mobile-entry.js'); export const DESKTOP_ENTRY_FILE = join(DIST_DIR, 'desktop-entry.js'); +export const STYPE_DEPS_MAP_FILE = join(DIST_DIR, 'style-deps-map.json'); export const JEST_CONFIG_FILE = join(CONFIG_DIR, 'jest.config.js'); export const BABEL_CONFIG_FILE = join(CONFIG_DIR, 'babel.config.js'); diff --git a/packages/vant-cli/src/compiler/gen-style-deps-map.ts b/packages/vant-cli/src/compiler/gen-style-deps-map.ts new file mode 100644 index 000000000..436471d6e --- /dev/null +++ b/packages/vant-cli/src/compiler/gen-style-deps-map.ts @@ -0,0 +1,96 @@ +/** + * Build style entry of all components + */ + +import { join } from 'path'; +import { existsSync, writeFileSync } from 'fs-extra'; +import { getComponents } from '../common'; +import { ES_DIR, STYPE_DEPS_MAP_FILE } from '../common/constant'; +import dependencyTree from 'dependency-tree'; + +interface DependencyObj { + [k: string]: DependencyObj; +} + +const components = getComponents(); +const STYLE_EXTS = ['.css', '.less', '.scss']; +const JS_EXTS = ['.js', '.jsx', '.ts', '.tsx', '.vue']; + +function getStylePath(component: string, ext = '.css'): string { + return join(ES_DIR, `${component}/index${ext}`); +} + +function checkStyleExists(component: string): boolean { + return STYLE_EXTS.some(ext => existsSync(getStylePath(component, ext))); +} + +function getScriptPath(component: string): string { + for (let i = 0; i < JS_EXTS.length; i++) { + const path = join(ES_DIR, component, `index${JS_EXTS[i]}`); + if (existsSync(path)) { + return path; + } + } + + return ''; +} + +function matchPath(path: string, component: string): boolean { + return path + .replace(ES_DIR, '') + .split('/') + .includes(component); +} + +function search(tree: DependencyObj, component: string, checkList: string[]) { + Object.keys(tree).forEach(key => { + search(tree[key], component, checkList); + components + .filter(item => matchPath(key, item)) + .forEach(item => { + if (!checkList.includes(item) && item !== component) { + checkList.push(item); + } + }); + }); +} + +// analyze component dependencies +function analyzeDeps(component: string) { + const checkList: string[] = []; + const filename = getScriptPath(component); + + if (!filename) { + return []; + } + + search( + dependencyTree({ + filename, + directory: ES_DIR, + filter: path => !~path.indexOf('node_modules'), + detective: { + es6: { + mixedImports: true + } + } + }), + component, + checkList + ); + + checkList.push(component); + + return checkList.filter(checkStyleExists); +} + +export function genStyleDepsMap() { + const map = components.reduce((map, component) => { + map[component] = analyzeDeps(component); + return map; + }, {} as Record); + + const content = JSON.stringify(map, null, 2); + + writeFileSync(STYPE_DEPS_MAP_FILE, content); +}