feat(cli): build style entry

This commit is contained in:
陈嘉涵 2019-11-21 16:03:29 +08:00
parent 4dbd444679
commit 2804d1f95e
6 changed files with 148 additions and 138 deletions

View File

@ -1,115 +0,0 @@
/* eslint-disable no-use-before-define */
/**
* Build style entry of all components
*/
const fs = require('fs-extra');
const path = require('path');
const dependencyTree = require('dependency-tree');
const components = require('./get-components')();
// replace seq for windows
function replaceSeq(path) {
return path.split(path.sep).join('/');
}
const whiteList = [
'info',
'icon',
'loading',
'cell',
'cell-group',
'button',
'overlay'
];
const dir = path.join(__dirname, '../es');
function destEntryFile(component, filename, ext = '') {
const deps = analyzeDependencies(component).map(dep =>
getStyleRelativePath(component, dep, ext)
);
const esEntry = path.join(dir, component, `style/${filename}`);
const libEntry = path.join(
__dirname,
'../lib',
component,
`style/${filename}`
);
const esContent = deps.map(dep => `import '${dep}';`).join('\n');
const libContent = deps.map(dep => `require('${dep}');`).join('\n');
fs.outputFileSync(esEntry, esContent);
fs.outputFileSync(libEntry, libContent);
}
// analyze component dependencies
function analyzeDependencies(component) {
const checkList = ['base'];
search(
dependencyTree({
directory: dir,
filename: path.join(dir, component, 'index.js'),
filter: path => !~path.indexOf('node_modules')
}),
component,
checkList
);
if (!whiteList.includes(component)) {
checkList.push(component);
}
return checkList.filter(item => checkComponentHasStyle(item));
}
function search(tree, component, checkList) {
Object.keys(tree).forEach(key => {
search(tree[key], component, checkList);
components
.filter(item =>
key
.replace(dir, '')
.split('/')
.includes(item)
)
.forEach(item => {
if (
!checkList.includes(item) &&
!whiteList.includes(item) &&
item !== component
) {
checkList.push(item);
}
});
});
}
function getStylePath(component, ext = '.css') {
if (component === 'base') {
return path.join(__dirname, `../es/style/base${ext}`);
}
return path.join(__dirname, `../es/${component}/index${ext}`);
}
function getStyleRelativePath(component, style, ext) {
return replaceSeq(
path.relative(
path.join(__dirname, `../es/${component}/style`),
getStylePath(style, ext)
)
);
}
function checkComponentHasStyle(component) {
return fs.existsSync(getStylePath(component));
}
components.forEach(component => {
// css entry
destEntryFile(component, 'index.js', '.css');
// less entry
destEntryFile(component, 'less.js', '.less');
});

View File

@ -27,6 +27,7 @@
"vue-template-compiler": "^2.6.10" "vue-template-compiler": "^2.6.10"
}, },
"devDependencies": { "devDependencies": {
"@types/dependency-tree": "^6.1.0",
"@types/eslint": "^6.1.3", "@types/eslint": "^6.1.3",
"@types/fs-extra": "^8.0.1", "@types/fs-extra": "^8.0.1",
"@types/html-webpack-plugin": "^3.2.1", "@types/html-webpack-plugin": "^3.2.1",

View File

@ -7,6 +7,7 @@ import { remove, copy, readdirSync } from 'fs-extra';
import { compileJs } from '../compiler/compile-js'; import { compileJs } from '../compiler/compile-js';
import { compileSfc } from '../compiler/compile-sfc'; import { compileSfc } from '../compiler/compile-sfc';
import { compileStyle } from '../compiler/compile-style'; import { compileStyle } from '../compiler/compile-style';
import { genStyleEntry } from '../compiler/gen-style-entry';
import { genPackageEntry } from '../compiler/gen-package-entry'; import { genPackageEntry } from '../compiler/gen-package-entry';
import { SRC_DIR, LIB_DIR, ES_DIR } from '../common/constant'; import { SRC_DIR, LIB_DIR, ES_DIR } from '../common/constant';
import { import {
@ -21,23 +22,33 @@ import {
async function compileDir(dir: string) { async function compileDir(dir: string) {
const files = readdirSync(dir); const files = readdirSync(dir);
files.forEach(async filename => { await Promise.all(
const filePath = join(dir, filename); files.map(filename => {
const filePath = join(dir, filename);
if (isDemoDir(filePath) || isTestDir(filePath)) { if (isDemoDir(filePath) || isTestDir(filePath)) {
await remove(filePath); return remove(filePath);
} else if (isDir(filePath)) { }
await compileDir(filePath);
} else if (isSfc(filePath)) { if (isDir(filePath)) {
await compileSfc(filePath); return compileDir(filePath);
} else if (isScript(filePath)) { }
await compileJs(filePath);
} else if (isStyle(filePath)) { if (isSfc(filePath)) {
await compileStyle(filePath); return compileSfc(filePath);
} else { }
await remove(filePath);
} if (isScript(filePath)) {
}); return compileJs(filePath);
}
if (isStyle(filePath)) {
return compileStyle(filePath);
}
return remove(filePath);
})
);
} }
function setModuleEnv(value: string) { function setModuleEnv(value: string) {
@ -80,6 +91,14 @@ export async function build() {
error('Build commonjs outputs'); error('Build commonjs outputs');
} }
start('Build style entry');
try {
genStyleEntry();
success('Build style entry');
} catch (err) {
error('Build style entry');
}
start('Build packed outputs'); start('Build packed outputs');
try { try {
genPackageEntry(); genPackageEntry();

View File

@ -88,13 +88,15 @@ export async function compileSfc(filePath: string) {
} }
// compile style part // compile style part
styles.forEach(async (style, index: number) => { await Promise.all(
const prefix = index !== 0 ? `-${index + 1}` : ''; styles.map((style, index: number) => {
const ext = style.lang || 'css'; const prefix = index !== 0 ? `-${index + 1}` : '';
const cssFilePath = replaceExt(filePath, `${prefix}.${ext}`); const ext = style.lang || 'css';
const cssFilePath = replaceExt(filePath, `-sfc${prefix}.${ext}`);
writeFileSync(cssFilePath, trim(style.content)); writeFileSync(cssFilePath, trim(style.content));
await compileStyle(cssFilePath); return compileStyle(cssFilePath);
}); })
);
} }

View File

@ -0,0 +1,98 @@
/* eslint-disable no-use-before-define */
/**
* Build style entry of all components
*/
import { sep, join, relative } from 'path';
import { existsSync, outputFileSync } from 'fs-extra';
import { getComponents } from '../common';
import { ES_DIR, LIB_DIR } from '../common/constant';
import dependencyTree from 'dependency-tree';
interface DependencyObj {
[k: string]: DependencyObj;
}
const components = getComponents();
// replace seq for windows
function replaceSeq(path: string) {
return path.split(sep).join('/');
}
function genEntry(component: string, filename: string, ext = '') {
const deps = analyzeDeps(component).map(dep =>
getStyleRelativePath(component, dep, ext)
);
const esEntry = join(ES_DIR, component, `style/${filename}`);
const libEntry = join(LIB_DIR, component, `style/${filename}`);
const esContent = deps.map(dep => `import '${dep}';`).join('\n');
const libContent = deps.map(dep => `require('${dep}');`).join('\n');
outputFileSync(esEntry, esContent);
outputFileSync(libEntry, libContent);
}
// analyze component dependencies
function analyzeDeps(component: string) {
const checkList = ['base'];
search(
dependencyTree({
directory: ES_DIR,
filename: join(ES_DIR, component, 'index.js'),
filter: path => !~path.indexOf('node_modules')
}),
component,
checkList
);
checkList.push(component);
return checkList.filter(checkStyleExists);
}
function search(tree: DependencyObj, component: string, checkList: string[]) {
Object.keys(tree).forEach(key => {
search(tree[key], component, checkList);
components
.filter(item =>
key
.replace(ES_DIR, '')
.split('/')
.includes(item)
)
.forEach(item => {
if (!checkList.includes(item) && item !== component) {
checkList.push(item);
}
});
});
}
function getStylePath(component: string, ext = '.css') {
if (component === 'base') {
return join(ES_DIR, `style/base${ext}`);
}
return join(ES_DIR, `${component}/index${ext}`);
}
function getStyleRelativePath(component: string, style: string, ext: string) {
return replaceSeq(
relative(join(ES_DIR, `${component}/style`), getStylePath(style, ext))
);
}
function checkStyleExists(component: string) {
return existsSync(getStylePath(component));
}
export function genStyleEntry() {
components.forEach(component => {
genEntry(component, 'index.js', '.css');
genEntry(component, 'less.js', '.less');
});
}

View File

@ -1089,6 +1089,11 @@
dependencies: dependencies:
"@types/node" "*" "@types/node" "*"
"@types/dependency-tree@^6.1.0":
version "6.1.0"
resolved "https://registry.yarnpkg.com/@types/dependency-tree/-/dependency-tree-6.1.0.tgz#12d30efd39b6caad29928d7ab3c39149feff09a5"
integrity sha512-x9b+ZZ9GSCGJq/0Hza0UMiNyxhUB3O2FOcSIDu95O+tmFQ/AhAY6bMhmktUsnPDOucBlQ6dPLUsdEZoejLNtdg==
"@types/eslint-visitor-keys@^1.0.0": "@types/eslint-visitor-keys@^1.0.0":
version "1.0.0" version "1.0.0"
resolved "https://registry.npm.taobao.org/@types/eslint-visitor-keys/download/@types/eslint-visitor-keys-1.0.0.tgz?cache=0&sync_timestamp=1572470950582&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Feslint-visitor-keys%2Fdownload%2F%40types%2Feslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" resolved "https://registry.npm.taobao.org/@types/eslint-visitor-keys/download/@types/eslint-visitor-keys-1.0.0.tgz?cache=0&sync_timestamp=1572470950582&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Feslint-visitor-keys%2Fdownload%2F%40types%2Feslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d"