mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
feat(cli): restart compile when vant config updated
This commit is contained in:
parent
2db6e2a44d
commit
b19b287276
@ -1,7 +1,13 @@
|
|||||||
import decamelize from 'decamelize';
|
import decamelize from 'decamelize';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
import { get } from 'lodash';
|
import { get } from 'lodash';
|
||||||
import { readdirSync, existsSync, lstatSync, readFileSync } from 'fs-extra';
|
import {
|
||||||
|
lstatSync,
|
||||||
|
existsSync,
|
||||||
|
readdirSync,
|
||||||
|
readFileSync,
|
||||||
|
outputFileSync
|
||||||
|
} from 'fs-extra';
|
||||||
import { CONFIG, SRC_DIR, WEBPACK_CONFIG_FILE } from './constant';
|
import { CONFIG, SRC_DIR, WEBPACK_CONFIG_FILE } from './constant';
|
||||||
|
|
||||||
export const EXT_REGEXP = /\.\w+$/;
|
export const EXT_REGEXP = /\.\w+$/;
|
||||||
@ -114,4 +120,18 @@ export function getCssLang(): string {
|
|||||||
return preprocessor;
|
return preprocessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Smarter outputFileSync
|
||||||
|
// Skip if content unchanged
|
||||||
|
export function smartOutputFile(filePath: string, content: string) {
|
||||||
|
if (existsSync(filePath)) {
|
||||||
|
const previousContent = readFileSync(filePath, 'utf-8');
|
||||||
|
|
||||||
|
if (previousContent === content) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
outputFileSync(filePath, content);
|
||||||
|
}
|
||||||
|
|
||||||
export { decamelize };
|
export { decamelize };
|
||||||
|
@ -1,14 +1,19 @@
|
|||||||
import { transformFileSync } from '@babel/core';
|
import { transformFileAsync } from '@babel/core';
|
||||||
import { removeSync, outputFileSync } from 'fs-extra';
|
import { removeSync, outputFileSync } from 'fs-extra';
|
||||||
import { replaceExt } from '../common';
|
import { replaceExt } from '../common';
|
||||||
|
|
||||||
export function compileJs(filePath: string) {
|
export function compileJs(filePath: string): Promise<undefined> {
|
||||||
const result = transformFileSync(filePath);
|
return new Promise((resolve, reject) => {
|
||||||
|
transformFileAsync(filePath)
|
||||||
|
.then(result => {
|
||||||
|
if (result) {
|
||||||
|
const jsFilePath = replaceExt(filePath, '.js');
|
||||||
|
|
||||||
if (result) {
|
removeSync(filePath);
|
||||||
const jsFilePath = replaceExt(filePath, '.js');
|
outputFileSync(jsFilePath, result.code);
|
||||||
|
resolve();
|
||||||
removeSync(filePath);
|
}
|
||||||
outputFileSync(jsFilePath, result.code);
|
})
|
||||||
}
|
.catch(reject);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import * as compiler from 'vue-template-compiler';
|
import * as compiler from 'vue-template-compiler';
|
||||||
import * as compileUtils from '@vue/component-compiler-utils';
|
import * as compileUtils from '@vue/component-compiler-utils';
|
||||||
import { parse } from 'path';
|
import { parse } from 'path';
|
||||||
import { removeSync, writeFileSync, readFileSync } from 'fs-extra';
|
import { remove, writeFileSync, readFileSync } from 'fs-extra';
|
||||||
import { replaceExt } from '../common';
|
import { replaceExt } from '../common';
|
||||||
import { compileJs } from './compile-js';
|
import { compileJs } from './compile-js';
|
||||||
import { compileStyle } from './compile-style';
|
import { compileStyle } from './compile-style';
|
||||||
@ -63,7 +63,14 @@ function compileTemplate(template: string) {
|
|||||||
return result.code;
|
return result.code;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function compileSfc(filePath: string) {
|
type CompileSfcOptions = {
|
||||||
|
skipStyle?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function compileSfc(
|
||||||
|
filePath: string,
|
||||||
|
options: CompileSfcOptions = {}
|
||||||
|
): Promise<any> {
|
||||||
const source = readFileSync(filePath, 'utf-8');
|
const source = readFileSync(filePath, 'utf-8');
|
||||||
const jsFilePath = replaceExt(filePath, '.js');
|
const jsFilePath = replaceExt(filePath, '.js');
|
||||||
|
|
||||||
@ -75,30 +82,44 @@ export async function compileSfc(filePath: string) {
|
|||||||
|
|
||||||
const { template, styles } = descriptor;
|
const { template, styles } = descriptor;
|
||||||
|
|
||||||
removeSync(filePath);
|
const tasks = [remove(filePath)];
|
||||||
|
|
||||||
// compile js part
|
// compile js part
|
||||||
if (descriptor.script) {
|
if (descriptor.script) {
|
||||||
let script = descriptor.script.content;
|
tasks.push(
|
||||||
script = injectStyle(script, styles, filePath);
|
new Promise((resolve, reject) => {
|
||||||
|
let script = descriptor.script!.content;
|
||||||
|
script = injectStyle(script, styles, filePath);
|
||||||
|
|
||||||
if (template) {
|
if (template) {
|
||||||
const render = compileTemplate(template.content);
|
const render = compileTemplate(template.content);
|
||||||
script = injectRender(script, render);
|
script = injectRender(script, render);
|
||||||
}
|
}
|
||||||
|
|
||||||
writeFileSync(jsFilePath, script);
|
writeFileSync(jsFilePath, script);
|
||||||
compileJs(jsFilePath);
|
compileJs(jsFilePath)
|
||||||
|
.then(resolve)
|
||||||
|
.catch(reject);
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// compile style part
|
// compile style part
|
||||||
await Promise.all(
|
if (!options.skipStyle) {
|
||||||
styles.map((style, index: number) => {
|
tasks.push(
|
||||||
const cssFilePath = getSfcStylePath(filePath, style.lang || 'css', index);
|
...styles.map((style, index: number) => {
|
||||||
|
const cssFilePath = getSfcStylePath(
|
||||||
|
filePath,
|
||||||
|
style.lang || 'css',
|
||||||
|
index
|
||||||
|
);
|
||||||
|
|
||||||
writeFileSync(cssFilePath, trim(style.content));
|
writeFileSync(cssFilePath, trim(style.content));
|
||||||
|
|
||||||
return compileStyle(cssFilePath);
|
return compileStyle(cssFilePath);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.all(tasks);
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,13 @@
|
|||||||
import webpack from 'webpack';
|
import webpack from 'webpack';
|
||||||
import WebpackDevServer from 'webpack-dev-server';
|
import WebpackDevServer from 'webpack-dev-server';
|
||||||
import { getPort } from 'portfinder';
|
import { getPort } from 'portfinder';
|
||||||
import { getStepper } from '../common/logger';
|
|
||||||
import { genPackageEntry } from './gen-package-entry';
|
|
||||||
import { genPacakgeStyle } from './gen-package-style';
|
|
||||||
import { genSiteMobileShared } from './gen-site-mobile-shared';
|
|
||||||
import { genSiteDesktopShared } from './gen-site-desktop-shared';
|
|
||||||
import { genStyleDepsMap } from './gen-style-deps-map';
|
|
||||||
import { siteDevConfig } from '../config/webpack.site.dev';
|
import { siteDevConfig } from '../config/webpack.site.dev';
|
||||||
import { sitePrdConfig } from '../config/webpack.site.prd';
|
import { sitePrdConfig } from '../config/webpack.site.prd';
|
||||||
|
|
||||||
const stpper = getStepper(4);
|
|
||||||
|
|
||||||
function watch() {
|
function watch() {
|
||||||
const server = new WebpackDevServer(
|
const server = new WebpackDevServer(
|
||||||
webpack(siteDevConfig),
|
webpack(siteDevConfig),
|
||||||
(siteDevConfig as any).devServer
|
siteDevConfig.devServer
|
||||||
);
|
);
|
||||||
|
|
||||||
getPort(
|
getPort(
|
||||||
@ -50,19 +42,9 @@ function build() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function compileSite(production = false) {
|
export async function compileSite(production = false) {
|
||||||
stpper.start('Prepare For Compilation');
|
|
||||||
await genStyleDepsMap();
|
|
||||||
genPackageEntry();
|
|
||||||
genPacakgeStyle();
|
|
||||||
genSiteMobileShared();
|
|
||||||
genSiteDesktopShared();
|
|
||||||
stpper.success('Prepare For Compilation');
|
|
||||||
|
|
||||||
stpper.start('Build Documentation Site');
|
|
||||||
if (production) {
|
if (production) {
|
||||||
await build();
|
await build();
|
||||||
} else {
|
} else {
|
||||||
watch();
|
watch();
|
||||||
}
|
}
|
||||||
stpper.success('Build Documentation Site');
|
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,6 @@
|
|||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
import { writeFileSync } from 'fs-extra';
|
import { pascalize, getComponents, smartOutputFile } from '../common';
|
||||||
import { pascalize, getComponents } from '../common';
|
import { SRC_DIR, PACKAGE_JSON, PACKAGE_ENTRY_FILE } from '../common/constant';
|
||||||
import {
|
|
||||||
SRC_DIR,
|
|
||||||
PACKAGE_JSON,
|
|
||||||
PACKAGE_ENTRY_FILE
|
|
||||||
} from '../common/constant';
|
|
||||||
|
|
||||||
const version = process.env.PACKAGE_VERSION || PACKAGE_JSON.version;
|
const version = process.env.PACKAGE_VERSION || PACKAGE_JSON.version;
|
||||||
|
|
||||||
@ -56,5 +51,5 @@ export default {
|
|||||||
};
|
};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
writeFileSync(PACKAGE_ENTRY_FILE, content);
|
smartOutputFile(PACKAGE_ENTRY_FILE, content);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
import { writeFileSync } from 'fs-extra';
|
import { replaceExt, smartOutputFile } from '../common';
|
||||||
import { replaceExt } from '../common';
|
|
||||||
import { CSS_LANG, getCssBaseFile } from '../common/css';
|
import { CSS_LANG, getCssBaseFile } from '../common/css';
|
||||||
import {
|
import {
|
||||||
SRC_DIR,
|
SRC_DIR,
|
||||||
@ -23,5 +22,5 @@ export function genPacakgeStyle() {
|
|||||||
.map((name: string) => `@import "${join(SRC_DIR, `${name}/index${ext}`)}";`)
|
.map((name: string) => `@import "${join(SRC_DIR, `${name}/index${ext}`)}";`)
|
||||||
.join('\n');
|
.join('\n');
|
||||||
|
|
||||||
writeFileSync(replaceExt(PACKAGE_STYLE_FILE, ext), content);
|
smartOutputFile(replaceExt(PACKAGE_STYLE_FILE, ext), content);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
import glob from 'fast-glob';
|
import glob from 'fast-glob';
|
||||||
import { join, parse } from 'path';
|
import { join, parse } from 'path';
|
||||||
import { existsSync, writeFileSync } from 'fs-extra';
|
import { existsSync } from 'fs-extra';
|
||||||
import { pascalize, removeExt, getComponents } from '../common';
|
import {
|
||||||
|
pascalize,
|
||||||
|
removeExt,
|
||||||
|
getComponents,
|
||||||
|
smartOutputFile
|
||||||
|
} from '../common';
|
||||||
import {
|
import {
|
||||||
SRC_DIR,
|
SRC_DIR,
|
||||||
DOCS_DIR,
|
DOCS_DIR,
|
||||||
@ -64,5 +69,5 @@ ${genExportConfig()}
|
|||||||
${genExportDocuments(documents)}
|
${genExportDocuments(documents)}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
writeFileSync(SITE_DESKTOP_SHARED_FILE, code);
|
smartOutputFile(SITE_DESKTOP_SHARED_FILE, code);
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
import { existsSync, ensureDirSync, writeFileSync } from 'fs-extra';
|
import { existsSync } from 'fs-extra';
|
||||||
import { decamelize, pascalize, removeExt, getComponents } from '../common';
|
import { decamelize, pascalize, removeExt, getComponents, smartOutputFile } from '../common';
|
||||||
import {
|
import {
|
||||||
CONFIG,
|
CONFIG,
|
||||||
SRC_DIR,
|
SRC_DIR,
|
||||||
DIST_DIR,
|
|
||||||
SITE_MODILE_SHARED_FILE
|
SITE_MODILE_SHARED_FILE
|
||||||
} from '../common/constant';
|
} from '../common/constant';
|
||||||
|
|
||||||
@ -64,6 +63,5 @@ export function genSiteMobileShared() {
|
|||||||
const components = getComponents();
|
const components = getComponents();
|
||||||
const code = genCode(components);
|
const code = genCode(components);
|
||||||
|
|
||||||
ensureDirSync(DIST_DIR);
|
smartOutputFile(SITE_MODILE_SHARED_FILE, code);
|
||||||
writeFileSync(SITE_MODILE_SHARED_FILE, code);
|
|
||||||
}
|
}
|
||||||
|
@ -6,22 +6,16 @@ import dependencyTree from 'dependency-tree';
|
|||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
import { compileJs } from './compile-js';
|
import { compileJs } from './compile-js';
|
||||||
import { compileSfc } from './compile-sfc';
|
import { compileSfc } from './compile-sfc';
|
||||||
import { compileStyle } from './compile-style';
|
import { CSS_LANG } from '../common/css';
|
||||||
|
import { SRC_DIR, DIST_DIR, STYPE_DEPS_JSON_FILE } from '../common/constant';
|
||||||
|
import { copySync, existsSync, readdirSync } from 'fs-extra';
|
||||||
import {
|
import {
|
||||||
isDir,
|
isDir,
|
||||||
isSfc,
|
isSfc,
|
||||||
isStyle,
|
|
||||||
isScript,
|
isScript,
|
||||||
getComponents
|
getComponents,
|
||||||
|
smartOutputFile
|
||||||
} from '../common';
|
} from '../common';
|
||||||
import { SRC_DIR, DIST_DIR, STYPE_DEPS_JSON_FILE } from '../common/constant';
|
|
||||||
import {
|
|
||||||
copy,
|
|
||||||
existsSync,
|
|
||||||
readdirSync,
|
|
||||||
writeFileSync,
|
|
||||||
ensureDirSync
|
|
||||||
} from 'fs-extra';
|
|
||||||
|
|
||||||
interface DependencyObj {
|
interface DependencyObj {
|
||||||
[k: string]: DependencyObj;
|
[k: string]: DependencyObj;
|
||||||
@ -30,10 +24,10 @@ interface DependencyObj {
|
|||||||
const components = getComponents();
|
const components = getComponents();
|
||||||
const TEMP_DIR = join(DIST_DIR, 'temp');
|
const TEMP_DIR = join(DIST_DIR, 'temp');
|
||||||
|
|
||||||
async function compileTempDir(dir: string) {
|
function compileTempDir(dir: string): Promise<unknown> {
|
||||||
const files = readdirSync(dir);
|
const files = readdirSync(dir);
|
||||||
|
|
||||||
await Promise.all(
|
return Promise.all(
|
||||||
files.map(filename => {
|
files.map(filename => {
|
||||||
const filePath = join(dir, filename);
|
const filePath = join(dir, filename);
|
||||||
|
|
||||||
@ -43,16 +37,12 @@ async function compileTempDir(dir: string) {
|
|||||||
|
|
||||||
if (filename.indexOf('index') !== -1) {
|
if (filename.indexOf('index') !== -1) {
|
||||||
if (isSfc(filePath)) {
|
if (isSfc(filePath)) {
|
||||||
return compileSfc(filePath);
|
return compileSfc(filePath, { skipStyle: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isScript(filePath)) {
|
if (isScript(filePath)) {
|
||||||
return compileJs(filePath);
|
return compileJs(filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isStyle(filePath)) {
|
|
||||||
return compileStyle(filePath);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
@ -81,7 +71,7 @@ function search(tree: DependencyObj, component: string, checkList: string[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getStylePath(component: string) {
|
function getStylePath(component: string) {
|
||||||
return join(TEMP_DIR, `${component}/index.css`);
|
return join(TEMP_DIR, `${component}/index.${CSS_LANG}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkStyleExists(component: string) {
|
function checkStyleExists(component: string) {
|
||||||
@ -147,27 +137,29 @@ function getSequence(depsMap: DepsMap) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function genStyleDepsMap() {
|
export async function genStyleDepsMap() {
|
||||||
const map = {} as DepsMap;
|
return new Promise(resolve => {
|
||||||
|
const map = {} as DepsMap;
|
||||||
|
|
||||||
await copy(SRC_DIR, TEMP_DIR);
|
copySync(SRC_DIR, TEMP_DIR);
|
||||||
await compileTempDir(TEMP_DIR);
|
compileTempDir(TEMP_DIR).then(() => {
|
||||||
|
components.filter(checkStyleExists).forEach(component => {
|
||||||
|
map[component] = analyzeDeps(component);
|
||||||
|
});
|
||||||
|
|
||||||
components.filter(checkStyleExists).forEach(component => {
|
const sequence = getSequence(map);
|
||||||
map[component] = analyzeDeps(component);
|
|
||||||
|
Object.keys(map).forEach(key => {
|
||||||
|
map[key] = map[key].sort(
|
||||||
|
(a, b) => sequence.indexOf(a) - sequence.indexOf(b)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
smartOutputFile(
|
||||||
|
STYPE_DEPS_JSON_FILE,
|
||||||
|
JSON.stringify({ map, sequence }, null, 2)
|
||||||
|
);
|
||||||
|
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const sequence = getSequence(map);
|
|
||||||
|
|
||||||
Object.keys(map).forEach(key => {
|
|
||||||
map[key] = map[key].sort(
|
|
||||||
(a, b) => sequence.indexOf(a) - sequence.indexOf(b)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
ensureDirSync(DIST_DIR);
|
|
||||||
|
|
||||||
writeFileSync(
|
|
||||||
STYPE_DEPS_JSON_FILE,
|
|
||||||
JSON.stringify({ map, sequence }, null, 2)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
28
packages/vant-cli/src/compiler/vant-cli-site-plugin.ts
Normal file
28
packages/vant-cli/src/compiler/vant-cli-site-plugin.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { Compiler } from 'webpack';
|
||||||
|
import { genPackageEntry } from './gen-package-entry';
|
||||||
|
import { genPacakgeStyle } from './gen-package-style';
|
||||||
|
import { genSiteMobileShared } from './gen-site-mobile-shared';
|
||||||
|
import { genSiteDesktopShared } from './gen-site-desktop-shared';
|
||||||
|
import { genStyleDepsMap } from './gen-style-deps-map';
|
||||||
|
|
||||||
|
const PLUGIN_NAME = 'VantCliSitePlugin';
|
||||||
|
|
||||||
|
export class VantCliSitePlugin {
|
||||||
|
apply(compiler: Compiler) {
|
||||||
|
compiler.hooks.beforeCompile.tapPromise(PLUGIN_NAME, this.genSiteEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
genSiteEntry() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
genStyleDepsMap()
|
||||||
|
.then(() => {
|
||||||
|
genPackageEntry();
|
||||||
|
genPacakgeStyle();
|
||||||
|
genSiteMobileShared();
|
||||||
|
genSiteDesktopShared();
|
||||||
|
resolve();
|
||||||
|
})
|
||||||
|
.catch(reject);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,7 @@ import HtmlWebpackPlugin from 'html-webpack-plugin';
|
|||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
import { baseConfig } from './webpack.base';
|
import { baseConfig } from './webpack.base';
|
||||||
import { getWebpackConfig } from '../common';
|
import { getWebpackConfig } from '../common';
|
||||||
|
import { VantCliSitePlugin } from '../compiler/vant-cli-site-plugin';
|
||||||
import {
|
import {
|
||||||
CONFIG,
|
CONFIG,
|
||||||
SITE_MODILE_SHARED_FILE,
|
SITE_MODILE_SHARED_FILE,
|
||||||
@ -45,6 +46,7 @@ export const siteDevBaseConfig = merge(baseConfig as any, {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
|
new VantCliSitePlugin(),
|
||||||
new HtmlWebpackPlugin({
|
new HtmlWebpackPlugin({
|
||||||
title,
|
title,
|
||||||
logo: siteConfig.logo,
|
logo: siteConfig.logo,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user