From dc42ddec3ab4be66f5473bcc31ff41be1953a94b Mon Sep 17 00:00:00 2001 From: luckyadam Date: Tue, 8 Oct 2019 20:48:24 +0800 Subject: [PATCH] =?UTF-8?q?feat(taro):=20cli=20=E9=85=8D=E5=90=88=20mini-r?= =?UTF-8?q?unner=20=E9=87=8D=E6=9E=84=20&&=20=E6=94=AF=E6=8C=81=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=20mini-runner=20=E7=BC=96=E8=AF=91=E6=8F=92=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/taro-cli/src/build.ts | 4 +- packages/taro-cli/src/mini/helper.ts | 299 +------------ packages/taro-cli/src/mini/index.ts | 273 +++--------- packages/taro-cli/src/plugin.ts | 397 +----------------- .../src/quickapp/template-rewriter.ts | 13 - packages/taro-cli/src/ui/common.ts | 8 +- packages/taro-cli/src/ui/h5.ts | 4 +- packages/taro-cli/src/ui/index.ts | 4 +- packages/taro-cli/src/ui/rn.ts | 9 +- packages/taro-cli/src/ui/ui.types.ts | 2 +- packages/taro-cli/src/ui/weapp.ts | 2 +- packages/taro-mini-runner/package.json | 6 +- packages/taro-mini-runner/src/index.ts | 6 + .../src/plugins/MiniPlugin.ts | 103 ++++- .../src/plugins/TaroLoadChunksPlugin.ts | 41 +- .../src/quickapp/style-rewriter.ts | 0 .../style/declaration/animation/index.ts | 0 .../style/declaration/background/index.ts | 0 .../style/declaration/border/index.ts | 0 .../quickapp/style/declaration/box/index.ts | 0 .../quickapp/style/declaration/color/index.ts | 0 .../style/declaration/component/index.ts | 0 .../style/declaration/dimension/index.ts | 0 .../style/declaration/flexbox/index.ts | 0 .../quickapp/style/declaration/font/index.ts | 0 .../src/quickapp/style/declaration/index.ts | 0 .../quickapp/style/declaration/list/index.ts | 0 .../style/declaration/margin/index.ts | 0 .../style/declaration/padding/index.ts | 0 .../style/declaration/position/index.ts | 0 .../quickapp/style/declaration/text/index.ts | 0 .../style/declaration/transform/transform.ts | 0 .../style/declaration/transition/index.ts | 0 .../style/declaration/visibility/index.ts | 0 .../src/quickapp/style/index.ts | 0 .../src/quickapp/style/selector/index.ts | 0 .../src/quickapp/style/util.ts | 0 .../src/quickapp/template-rewriter.ts | 13 + .../src/quickapp/template/constant.ts | 0 .../src/quickapp/template/node.ts | 0 .../src/quickapp/template/parser.ts | 0 .../src/quickapp/template/serialize.ts | 0 .../src/quickapp/template/tag/index.ts | 0 .../src/quickapp/template/tag/span/index.ts | 0 .../template/tag/taro-camera/index.ts | 0 .../template/tag/taro-canvas/index.ts | 0 .../quickapp/template/tag/taro-image/index.ts | 0 .../quickapp/template/tag/taro-input/index.ts | 0 .../quickapp/template/tag/taro-label/index.ts | 0 .../quickapp/template/tag/taro-map/index.ts | 0 .../template/tag/taro-picker/index.ts | 0 .../template/tag/taro-textarea/index.ts | 0 .../quickapp/template/tag/taro-video/index.ts | 0 .../src/quickapp/template/tag/text/index.ts | 0 .../src/quickapp/template/utils.ts | 0 packages/taro-mini-runner/src/utils/types.ts | 3 +- .../src/webpack/build.conf.ts | 35 +- .../taro-mini-runner/src/webpack/chain.ts | 48 ++- packages/taro-webpack-runner/src/index.ts | 2 +- 59 files changed, 322 insertions(+), 950 deletions(-) delete mode 100644 packages/taro-cli/src/quickapp/template-rewriter.ts rename packages/{taro-cli => taro-mini-runner}/src/quickapp/style-rewriter.ts (100%) rename packages/{taro-cli => taro-mini-runner}/src/quickapp/style/declaration/animation/index.ts (100%) rename packages/{taro-cli => taro-mini-runner}/src/quickapp/style/declaration/background/index.ts (100%) rename packages/{taro-cli => taro-mini-runner}/src/quickapp/style/declaration/border/index.ts (100%) rename packages/{taro-cli => taro-mini-runner}/src/quickapp/style/declaration/box/index.ts (100%) rename packages/{taro-cli => taro-mini-runner}/src/quickapp/style/declaration/color/index.ts (100%) rename packages/{taro-cli => taro-mini-runner}/src/quickapp/style/declaration/component/index.ts (100%) rename packages/{taro-cli => taro-mini-runner}/src/quickapp/style/declaration/dimension/index.ts (100%) rename packages/{taro-cli => taro-mini-runner}/src/quickapp/style/declaration/flexbox/index.ts (100%) rename packages/{taro-cli => taro-mini-runner}/src/quickapp/style/declaration/font/index.ts (100%) rename packages/{taro-cli => taro-mini-runner}/src/quickapp/style/declaration/index.ts (100%) rename packages/{taro-cli => taro-mini-runner}/src/quickapp/style/declaration/list/index.ts (100%) rename packages/{taro-cli => taro-mini-runner}/src/quickapp/style/declaration/margin/index.ts (100%) rename packages/{taro-cli => taro-mini-runner}/src/quickapp/style/declaration/padding/index.ts (100%) rename packages/{taro-cli => taro-mini-runner}/src/quickapp/style/declaration/position/index.ts (100%) rename packages/{taro-cli => taro-mini-runner}/src/quickapp/style/declaration/text/index.ts (100%) rename packages/{taro-cli => taro-mini-runner}/src/quickapp/style/declaration/transform/transform.ts (100%) rename packages/{taro-cli => taro-mini-runner}/src/quickapp/style/declaration/transition/index.ts (100%) rename packages/{taro-cli => taro-mini-runner}/src/quickapp/style/declaration/visibility/index.ts (100%) rename packages/{taro-cli => taro-mini-runner}/src/quickapp/style/index.ts (100%) rename packages/{taro-cli => taro-mini-runner}/src/quickapp/style/selector/index.ts (100%) rename packages/{taro-cli => taro-mini-runner}/src/quickapp/style/util.ts (100%) create mode 100644 packages/taro-mini-runner/src/quickapp/template-rewriter.ts rename packages/{taro-cli => taro-mini-runner}/src/quickapp/template/constant.ts (100%) rename packages/{taro-cli => taro-mini-runner}/src/quickapp/template/node.ts (100%) rename packages/{taro-cli => taro-mini-runner}/src/quickapp/template/parser.ts (100%) rename packages/{taro-cli => taro-mini-runner}/src/quickapp/template/serialize.ts (100%) rename packages/{taro-cli => taro-mini-runner}/src/quickapp/template/tag/index.ts (100%) rename packages/{taro-cli => taro-mini-runner}/src/quickapp/template/tag/span/index.ts (100%) rename packages/{taro-cli => taro-mini-runner}/src/quickapp/template/tag/taro-camera/index.ts (100%) rename packages/{taro-cli => taro-mini-runner}/src/quickapp/template/tag/taro-canvas/index.ts (100%) rename packages/{taro-cli => taro-mini-runner}/src/quickapp/template/tag/taro-image/index.ts (100%) rename packages/{taro-cli => taro-mini-runner}/src/quickapp/template/tag/taro-input/index.ts (100%) rename packages/{taro-cli => taro-mini-runner}/src/quickapp/template/tag/taro-label/index.ts (100%) rename packages/{taro-cli => taro-mini-runner}/src/quickapp/template/tag/taro-map/index.ts (100%) rename packages/{taro-cli => taro-mini-runner}/src/quickapp/template/tag/taro-picker/index.ts (100%) rename packages/{taro-cli => taro-mini-runner}/src/quickapp/template/tag/taro-textarea/index.ts (100%) rename packages/{taro-cli => taro-mini-runner}/src/quickapp/template/tag/taro-video/index.ts (100%) rename packages/{taro-cli => taro-mini-runner}/src/quickapp/template/tag/text/index.ts (100%) rename packages/{taro-cli => taro-mini-runner}/src/quickapp/template/utils.ts (100%) diff --git a/packages/taro-cli/src/build.ts b/packages/taro-cli/src/build.ts index b63c4ddeed71..b6bdc57f7a55 100644 --- a/packages/taro-cli/src/build.ts +++ b/packages/taro-cli/src/build.ts @@ -95,7 +95,7 @@ export default class Builder { } buildForMini (appPath: string, buildOptions: IBuildOptions) { - require('./mini/webpack').build(appPath, buildOptions, this) + require('./mini').build(appPath, buildOptions, null, this) } buildForRN (appPath: string, { watch }) { @@ -116,6 +116,6 @@ export default class Builder { return } console.log(chalk.green(`开始编译${typeMap[platform]}小程序插件`)) - require('./plugin').build(appPath, { watch, platform }) + require('./plugin').build(appPath, { watch, platform }, this) } } diff --git a/packages/taro-cli/src/mini/helper.ts b/packages/taro-cli/src/mini/helper.ts index 9e848742adb4..42d3f244e13f 100644 --- a/packages/taro-cli/src/mini/helper.ts +++ b/packages/taro-cli/src/mini/helper.ts @@ -2,67 +2,32 @@ import * as fs from 'fs-extra' import * as path from 'path' import { execSync } from 'child_process' -import chalk from 'chalk' import * as _ from 'lodash' import * as ora from 'ora' -import { Config } from '@tarojs/taro' +import chalk from 'chalk' import { IProjectConfig, ITaroManifestConfig } from '@tarojs/taro/types/compile' -import wxTransformer from '@tarojs/transformer-wx' -import getHashName from '../util/hash' import { BUILD_TYPES, MINI_APP_FILES, IMINI_APP_FILE_TYPE, PROJECT_CONFIG, - processTypeEnum, - REG_SCRIPTS, - NODE_MODULES_REG, - taroJsQuickAppComponents, - PARSE_AST_TYPE, NODE_MODULES } from '../util/constants' import { resolveScriptPath, - isAliasPath, - replaceAliasPath, - promoteRelativePath, - isNpmPkg, - printLog, - generateEnvList, - generateConstantsList, isEmptyObject, recursiveFindNodeModules, - getBabelConfig, - extnameExpRegOf, - generateAlipayPath, - unzip, + shouldUseCnpm, shouldUseYarn, - shouldUseCnpm + unzip } from '../util' -import { downloadGithubRepoLatestRelease } from '../util/dowload' -import { resolveNpmPkgMainPath } from '../util/resolve_npm_files' -import { resolveNpmSync } from '../util/npm' - import { IOption, INpmConfig } from '../util/types' import CONFIG from '../config' - -import { - IComponentObj, - IBuildResult, - IDependency -} from './interface' -import { getNpmOutputDir } from '../util/npmExact' -import { parseAst } from './astProcess' - -const isCopyingFiles: Map = new Map() -const dependencyTree: Map = new Map() -const hasBeenBuiltComponents: Set = new Set() -const componentExportsMap = new Map() -const depComponents = new Map() +import { downloadGithubRepoLatestRelease } from '../util/dowload' export interface IBuildData { appPath: string, @@ -76,16 +41,12 @@ export interface IBuildData { entryFileName: string, projectConfig: IProjectConfig, npmConfig: INpmConfig, - appConfig: Config, - pageConfigs: Map, alias: IOption, compileConfig: {[k: string]: any}, isProduction: boolean, buildAdapter: BUILD_TYPES, outputFilesTypes: IMINI_APP_FILE_TYPE, - constantsReplaceList: IOption, nodeModulesPath: string, - npmOutputDir: string, jsxAttributeNameReplace?: { [key: string]: any }, @@ -94,19 +55,6 @@ export interface IBuildData { let BuildData: IBuildData -export const shouldTransformAgain = function () { - const babelConfig = getBabelConfig(BuildData.projectConfig!.babel) - const pluginsStr = JSON.stringify(babelConfig.plugins) - if (/transform-runtime/.test(pluginsStr)) { - return true - } - return false -} - -export function setAppConfig (appConfig: Config) { - BuildData.appConfig = appConfig -} - export function setIsProduction (isProduction: boolean) { BuildData.isProduction = isProduction } @@ -115,7 +63,7 @@ export function setQuickappManifest (quickappManifest: ITaroManifestConfig) { BuildData.quickappManifest = quickappManifest } -export function setBuildData (appPath: string, adapter: BUILD_TYPES): IBuildData { +export function setBuildData (appPath: string, adapter: BUILD_TYPES, options?: Partial | null): IBuildData { const configDir = path.join(appPath, PROJECT_CONFIG) const projectConfig = require(configDir)(_.merge) const sourceDirName = projectConfig.sourceRoot || CONFIG.SOURCE_DIR @@ -146,16 +94,10 @@ export function setBuildData (appPath: string, adapter: BUILD_TYPES): IBuildData npmConfig, alias: pathAlias, isProduction: false, - appConfig: {}, - pageConfigs: new Map(), compileConfig: useCompileConf, buildAdapter: adapter, outputFilesTypes: MINI_APP_FILES[adapter], - constantsReplaceList: Object.assign({}, generateEnvList(projectConfig.env || {}), generateConstantsList(projectConfig.defineConstants || {}), { - 'process.env.TARO_ENV': adapter - }), nodeModulesPath: recursiveFindNodeModules(path.join(appPath, NODE_MODULES)), - npmOutputDir: getNpmOutputDir(outputDir, configDir, npmConfig), jsxAttributeNameReplace: weappConf.jsxAttributeNameReplace || {} } // 可以自定义输出文件类型 @@ -166,7 +108,9 @@ export function setBuildData (appPath: string, adapter: BUILD_TYPES): IBuildData BuildData.originalOutputDir = BuildData.outputDir BuildData.outputDirName = `${BuildData.outputDirName}/src` BuildData.outputDir = path.join(BuildData.appPath, BuildData.outputDirName) - BuildData.npmOutputDir = getNpmOutputDir(BuildData.outputDir, BuildData.configDir, BuildData.npmConfig) + } + if (options) { + Object.assign(BuildData, options) } return BuildData @@ -176,229 +120,10 @@ export function getBuildData (): IBuildData { return BuildData } -export function getDependencyTree (): Map { - return dependencyTree -} - -export function setHasBeenBuiltComponents (componentPath: string) { - hasBeenBuiltComponents.add(componentPath) -} - -export function getHasBeenBuiltComponents () { - return hasBeenBuiltComponents -} - -export function isComponentHasBeenBuilt (componentPath: string): boolean { - return hasBeenBuiltComponents.has(componentPath) -} - -export function deleteHasBeenBuiltComponent (filePath) { - if (hasBeenBuiltComponents.has(filePath)) { - hasBeenBuiltComponents.delete(filePath) - } -} - -export function setComponentExportsMap (key: string, value: IComponentObj[]) { - componentExportsMap.set(key, value) -} - -export function getComponentExportsMapItem (key: string): IComponentObj[] | void { - return componentExportsMap.get(key) -} - -export function getComponentExportsMap (): Map { - return componentExportsMap -} - -export function getDepComponents (): Map { - return depComponents -} - -export function buildUsingComponents ( - filePath: string, - components: IComponentObj[], - isComponent?: boolean -): IOption { - const { buildAdapter } = getBuildData() - const usingComponents = Object.create(null) - const pathAlias = BuildData.projectConfig.alias || {} - for (const component of components) { - let componentPath = component.path - if (isAliasPath(componentPath as string, pathAlias)) { - componentPath = replaceAliasPath(filePath, componentPath as string, pathAlias) - } - componentPath = resolveScriptPath(path.resolve(filePath, '..', componentPath as string)) - if (fs.existsSync(componentPath)) { - componentPath = promoteRelativePath(path.relative(filePath, componentPath)) - } else { - componentPath = component.path - } - if (buildAdapter === BUILD_TYPES.ALIPAY) { - componentPath = generateAlipayPath(componentPath) - } - if (component.name) { - const componentName = component.name.split('|')[0] - usingComponents[componentName] = (componentPath as string).replace(extnameExpRegOf(componentPath as string), '') - } - } - return Object.assign({}, isComponent ? { component: true } : { usingComponents: {} }, components.length ? { - usingComponents - } : {}) -} - -export function getRealComponentsPathList ( - filePath: string, - components: IComponentObj[] -): IComponentObj[] { - const { appPath, isProduction, buildAdapter, projectConfig, npmConfig } = BuildData - const pathAlias = projectConfig.alias || {} - return components.length ? components.map(component => { - let componentPath = component.path - if (isAliasPath(componentPath as string, pathAlias)) { - componentPath = replaceAliasPath(filePath, componentPath as string, pathAlias) - } - if (isNpmPkg(componentPath as string)) { - try { - componentPath = resolveNpmPkgMainPath(componentPath as string, isProduction, npmConfig, buildAdapter, appPath) - } catch (err) { - console.log(err) - } - } else { - componentPath = path.resolve(path.dirname(filePath), componentPath as string) - componentPath = resolveScriptPath(componentPath) - } - if (componentPath && isFileToBePage(componentPath)) { - printLog(processTypeEnum.ERROR, '组件引用', `文件${component.path}已经在 app.js 中被指定为页面,不能再作为组件来引用!`) - } - return { - path: componentPath, - name: component.name, - type: component.type - } - }) : [] -} - -export function isFileToBePage (filePath: string): boolean { - let isPage = false - const { appConfig, sourceDir } = BuildData - const extname = path.extname(filePath) - const pages = appConfig.pages || [] - const filePathWithoutExt = filePath.replace(extname, '') - pages.forEach(page => { - if (filePathWithoutExt === path.join(sourceDir, page)) { - isPage = true - } - }) - return isPage && REG_SCRIPTS.test(extname) -} - -export function getDepStyleList ( - outputFilePath: string, - buildDepComponentsResult: IBuildResult[] -): string[] { - const { sourceDir, outputDir } = BuildData - let depWXSSList: string[] = [] - if (buildDepComponentsResult.length) { - depWXSSList = buildDepComponentsResult.map(item => { - let wxss = item.wxss - wxss = wxss.replace(sourceDir, outputDir) - wxss = promoteRelativePath(path.relative(outputFilePath, wxss)) - return wxss - }) - } - return depWXSSList -} - -export function initCopyFiles () { - isCopyingFiles.clear() -} - -export function copyFilesFromSrcToOutput (files: string[], cb?: (sourceFilePath: string, outputFilePath: string) => void) { - const { nodeModulesPath, npmOutputDir, sourceDir, outputDir, appPath, projectConfig } = BuildData - const adapterConfig = Object.assign({}, projectConfig.weapp) - files.forEach(file => { - let outputFilePath - if (NODE_MODULES_REG.test(file)) { - outputFilePath = file.replace(nodeModulesPath, npmOutputDir) - } else { - if (adapterConfig.publicPath && adapterConfig.staticDirectory) { - const hashName = getHashName(file) - const staticPath = path.join(appPath, adapterConfig.staticDirectory, projectConfig.projectName || '') - outputFilePath = `${staticPath}/${hashName}` - } else { - outputFilePath = file.replace(sourceDir, outputDir) - } - } - if (isCopyingFiles.get(outputFilePath)) { - return - } - isCopyingFiles.set(outputFilePath, true) - let modifySrc = file.replace(appPath + path.sep, '') - modifySrc = modifySrc.split(path.sep).join('/') - let modifyOutput = outputFilePath.replace(appPath + path.sep, '') - modifyOutput = modifyOutput.split(path.sep).join('/') - printLog(processTypeEnum.COPY, '文件', modifyOutput) - if (!fs.existsSync(file)) { - printLog(processTypeEnum.ERROR, '文件', `${modifySrc} 不存在`) - } else { - fs.ensureDir(path.dirname(outputFilePath)) - if (file === outputFilePath) { - return - } - if (cb) { - cb(file, outputFilePath) - } else { - fs.copySync(file, outputFilePath) - } - } - }) -} - -export function getTaroJsQuickAppComponentsPath () { - const taroJsQuickAppComponentsPkg = resolveNpmSync(taroJsQuickAppComponents, BuildData.nodeModulesPath) - if (!taroJsQuickAppComponentsPkg) { - printLog(processTypeEnum.ERROR, '包安装', `缺少包 ${taroJsQuickAppComponents},请安装!`) - process.exit(0) - } - return path.join(path.dirname(taroJsQuickAppComponentsPkg as string), 'src/components') -} - -const SCRIPT_CONTENT_REG = /]*>([\s\S]*?)<\/script>/gm - -export function getImportTaroSelfComponents (filePath, taroSelfComponents) { - const importTaroSelfComponents = new Set<{ path: string, name: string }>() - const taroJsQuickAppComponentsPath = getTaroJsQuickAppComponentsPath() - taroSelfComponents.forEach(c => { - const cPath = path.join(taroJsQuickAppComponentsPath, c) - const cMainPath = path.join(cPath, 'index') - const cFiles = fs.readdirSync(cPath).map(item => path.join(cPath, item)) - copyFilesFromSrcToOutput(cFiles, (sourceFilePath, outputFilePath) => { - if (fs.existsSync(sourceFilePath)) { - const fileContent = fs.readFileSync(sourceFilePath).toString() - const match = SCRIPT_CONTENT_REG.exec(fileContent) - if (match) { - const scriptContent = match[1] - const transformResult = wxTransformer({ - code: scriptContent, - sourcePath: sourceFilePath, - isNormal: true, - isTyped: false, - adapter: BUILD_TYPES.QUICKAPP - }) - const res = parseAst(PARSE_AST_TYPE.NORMAL, transformResult.ast, [], sourceFilePath, outputFilePath) - const newFileContent = fileContent.replace(SCRIPT_CONTENT_REG, ``) - fs.ensureDirSync(path.dirname(outputFilePath)) - fs.writeFileSync(outputFilePath, newFileContent) - } - } - }) - const cRelativePath = promoteRelativePath(path.relative(filePath, cMainPath.replace(BuildData.nodeModulesPath, BuildData.npmOutputDir))) - importTaroSelfComponents.add({ - path: cRelativePath, - name: c - }) - }) - return importTaroSelfComponents +export function setOutputDirName (outputDirName) { + BuildData.originalOutputDir = BuildData.outputDir + BuildData.outputDirName = outputDirName + BuildData.outputDir = path.join(BuildData.appPath, BuildData.outputDirName) } export async function prepareQuickAppEnvironment (buildData: IBuildData) { diff --git a/packages/taro-cli/src/mini/index.ts b/packages/taro-cli/src/mini/index.ts index 762b92173947..920423df1cb5 100644 --- a/packages/taro-cli/src/mini/index.ts +++ b/packages/taro-cli/src/mini/index.ts @@ -1,49 +1,26 @@ import * as fs from 'fs-extra' import * as path from 'path' -import * as os from 'os' - import chalk from 'chalk' -import * as _ from 'lodash' -import * as ora from 'ora' -import { execSync } from 'child_process' -import { - printLog, - getInstalledNpmPkgVersion, - getPkgVersion, - copyFiles, - unzip, - shouldUseYarn, - shouldUseCnpm, - resolvePureScriptPath, - checkCliAndFrameworkVersion -} from '../util' -import { processTypeEnum, BUILD_TYPES } from '../util/constants' -import { IMiniAppBuildConfig } from '../util/types' +import { IBuildOptions } from '../util/types' +import { BUILD_TYPES, processTypeEnum } from '../util/constants' +import * as npmProcess from '../util/npm' +import { getBabelConfig, getInstalledNpmPkgVersion, getPkgVersion, printLog, checkCliAndFrameworkVersion } from '../util' +import Builder from '../build' import * as defaultManifestJSON from '../config/manifest.default.json' import { setBuildData, - getBuildData, setIsProduction, - setAppConfig, - IBuildData, - setQuickappManifest + getBuildData, + setQuickappManifest, + prepareQuickAppEnvironment, + runQuickApp, + IBuildData } from './helper' -import { buildEntry } from './entry' -import { buildPages, buildSinglePage } from './page' -import { watchFiles } from './watch' -import { downloadGithubRepoLatestRelease } from '../util/dowload' -import { buildSingleComponent } from './component' function buildProjectConfig () { const { buildAdapter, sourceDir, outputDir, outputDirName, appPath } = getBuildData() - - if (buildAdapter === BUILD_TYPES.JD) { - // 京东小程序暂不支持 project.config.json - return - } - let projectConfigFileName = `project.${buildAdapter}.json` if (buildAdapter === BUILD_TYPES.WEAPP) { projectConfigFileName = 'project.config.json' @@ -112,166 +89,16 @@ function readQuickAppManifest () { return quickappJSON } -function generateQuickAppManifest (quickappJSON: any) { - const { appConfig, pageConfigs, outputDir, projectConfig } = getBuildData() - // 生成 router - const pages = (appConfig.pages as string[]).concat() - const routerPages = {} - const customPageConfig = quickappJSON.customPageConfig || {} - - pages.forEach(element => { - const customConfig = customPageConfig[element] - const pageConf: any = { - component: path.basename(element) - } - if (customConfig) { - const filter = customConfig.filter - const launchMode = customConfig.launchMode - if (filter) { - pageConf.filter = filter - } - if (launchMode) { - pageConf.launchMode = launchMode - } - } - routerPages[path.dirname(element)] = pageConf - }) - delete quickappJSON.customPageConfig - const routerEntry = pages.shift() - const router = { - entry: path.dirname(routerEntry as string), - pages: routerPages - } - // 生成 display - const display = JSON.parse(JSON.stringify(appConfig.window || {})) - display.pages = {} - pageConfigs.forEach((item, page) => { - if (item) { - display.pages[path.dirname(page)] = item - } - }) - quickappJSON.router = router - quickappJSON.display = display - quickappJSON.config = Object.assign({}, quickappJSON.config, { - designWidth: projectConfig.designWidth || 750 - }) - if (appConfig.window && appConfig.window.navigationStyle === 'custom') { - quickappJSON.display.titleBar = false - delete quickappJSON.display.navigationStyle - } - fs.writeFileSync(path.join(outputDir, 'manifest.json'), JSON.stringify(quickappJSON, null, 2)) -} - -async function prepareQuickAppEnvironment (buildData: IBuildData) { - let isReady = false - let needDownload = false - let needInstall = false - const originalOutputDir = buildData.originalOutputDir - console.log() - if (fs.existsSync(path.join(buildData.originalOutputDir, 'sign'))) { - needDownload = false - } else { - needDownload = true - } - if (needDownload) { - const getSpinner = ora('开始下载快应用运行容器...').start() - await downloadGithubRepoLatestRelease('NervJS/quickapp-container', buildData.appPath, originalOutputDir) - await unzip(path.join(originalOutputDir, 'download_temp.zip')) - getSpinner.succeed('快应用运行容器下载完成') - } else { - console.log(`${chalk.green('✔ ')} 快应用容器已经准备好`) - } - process.chdir(originalOutputDir) - console.log() - if (fs.existsSync(path.join(originalOutputDir, 'node_modules'))) { - needInstall = false - } else { - needInstall = true - } - if (needInstall) { - const isWindows = os.platform() === 'win32' - let command - if (shouldUseYarn()) { - if(!isWindows) { - command = 'NODE_ENV=development yarn install' - } else { - command = 'yarn install' - } - } else if (shouldUseCnpm()) { - if(!isWindows) { - command = 'NODE_ENV=development cnpm install' - } else { - command = 'cnpm install' - } - } else { - if(!isWindows) { - command = 'NODE_ENV=development npm install' - } else { - command = 'npm install' - } - } - const installSpinner = ora(`安装快应用依赖环境, 需要一会儿...`).start() - try { - const stdout = execSync(command) - installSpinner.color = 'green' - installSpinner.succeed('安装成功') - console.log(`${stdout}`) - isReady = true - } catch (error) { - installSpinner.color = 'red' - installSpinner.fail(chalk.red(`快应用依赖环境安装失败,请进入 ${path.basename(originalOutputDir)} 重新安装!`)) - console.log(`${error}`) - isReady = false - } - } else { - console.log(`${chalk.green('✔ ')} 快应用依赖已经安装好`) - isReady = true - } - return isReady -} - -async function runQuickApp (isWatch: boolean | void, buildData: IBuildData, port?: number, release?: boolean) { - const originalOutputDir = buildData.originalOutputDir - const { compile } = require(require.resolve('hap-toolkit/lib/commands/compile', { paths: [originalOutputDir] })) - if (isWatch) { - const { launchServer } = require(require.resolve('@hap-toolkit/server', { paths: [originalOutputDir] })) - launchServer({ - port: port || 12306, - watch: isWatch, - clearRecords: false, - disableADB: false - }) - compile('native', 'dev', true) - } else { - if (!release) { - compile('native', 'dev', false) - } else { - compile('native', 'prod', false) - } - } -} - -export async function build ( - appPath: string, - { - watch, - adapter = BUILD_TYPES.WEAPP, - envHasBeenSet = false, - port, - release, - page, - component - }: IMiniAppBuildConfig -) { - const buildData = envHasBeenSet ? getBuildData() : setBuildData(appPath, adapter) - const isQuickApp = adapter === BUILD_TYPES.QUICKAPP - let quickappJSON - await checkCliAndFrameworkVersion(appPath, adapter) - process.env.TARO_ENV = adapter +export async function build (appPath: string, { watch, type = BUILD_TYPES.WEAPP, envHasBeenSet = false, port, release }: IBuildOptions, customBuildData: Partial | null | undefined, builder: Builder) { + const buildData = setBuildData(appPath, type, customBuildData) + const isQuickApp = type === BUILD_TYPES.QUICKAPP + await checkCliAndFrameworkVersion(appPath, type) + process.env.TARO_ENV = type if (!envHasBeenSet) { setIsProduction(process.env.NODE_ENV === 'production' || !watch) } fs.ensureDirSync(buildData.outputDir) + let quickappJSON if (!isQuickApp) { buildProjectConfig() await buildFrameworkInfo() @@ -279,29 +106,11 @@ export async function build ( quickappJSON = readQuickAppManifest() setQuickappManifest(quickappJSON) } - if (!isQuickApp) { - copyFiles(appPath, buildData.projectConfig.copy) - } - if (page) { - const pagePath = path.resolve(appPath, page).replace(buildData.sourceDir, '') - await buildSinglePage(pagePath) - return - } - if (component) { - const componentPath = resolvePureScriptPath(path.resolve(appPath, component)) - await buildSingleComponent({ - path: componentPath - }) - return - } - const appConfig = await buildEntry() - setAppConfig(appConfig) - await buildPages() - if (watch) { - watchFiles() - } + + await buildWithWebpack({ + appPath + }, builder) if (isQuickApp) { - generateQuickAppManifest(quickappJSON) const isReady = await prepareQuickAppEnvironment(buildData) if (!isReady) { console.log() @@ -309,7 +118,47 @@ export async function build ( process.exit(0) return } - copyFiles(appPath, buildData.projectConfig.copy) await runQuickApp(watch, buildData, port, release) } } + +async function buildWithWebpack ({ appPath }: { appPath: string }, builder) { + const { + entryFilePath, + buildAdapter, + projectConfig, + isProduction, + alias, + sourceDirName, + outputDirName, + nodeModulesPath, + quickappManifest + } = getBuildData() + const miniRunner = await npmProcess.getNpmPkg('@tarojs/mini-runner', appPath) + const babelConfig = getBabelConfig(projectConfig.babel) + const miniRunnerOpts = { + entry: { + app: [entryFilePath] + }, + alias, + copy: projectConfig.copy, + sourceRoot: sourceDirName, + outputRoot: outputDirName, + buildAdapter, + babel: babelConfig, + csso: projectConfig.csso, + sass: projectConfig.sass, + uglify: projectConfig.uglify, + plugins: projectConfig.plugins, + projectName: projectConfig.projectName, + isWatch: !isProduction, + env: projectConfig.env, + defineConstants: projectConfig.defineConstants, + designWidth: projectConfig.designWidth, + deviceRatio: projectConfig.deviceRatio, + nodeModulesPath, + quickappJSON: quickappManifest, + ...projectConfig.mini + } + await miniRunner(appPath, miniRunnerOpts, builder) +} diff --git a/packages/taro-cli/src/plugin.ts b/packages/taro-cli/src/plugin.ts index 6417060322c2..c5c6a0739711 100644 --- a/packages/taro-cli/src/plugin.ts +++ b/packages/taro-cli/src/plugin.ts @@ -1,58 +1,29 @@ import * as fs from 'fs-extra' import * as path from 'path' -import * as glob from 'glob' import chalk from 'chalk' -import * as chokidar from 'chokidar' import * as _ from 'lodash' -import * as Util from './util' import { - BUILD_TYPES, - REG_SCRIPT, - REG_STYLE, - REG_FONT, - REG_IMAGE, - REG_MEDIA, - REG_TYPESCRIPT, - processTypeEnum, - isWindows + BUILD_TYPES } from './util/constants' -import { buildEntry } from './mini/entry' -import { buildPages, buildSinglePage } from './mini/page' -import { build as buildWeapp } from './mini' import { - getRealComponentsPathList, - isFileToBePage, - isComponentHasBeenBuilt, - deleteHasBeenBuiltComponent, - getDependencyTree, - getBuildData, - setAppConfig, - setIsProduction, - setBuildData + getBuildData } from './mini/helper' -import { buildDepComponents, buildSingleComponent, getComponentsNamedMap } from './mini/component' -import { compileDepScripts, initCompileScripts } from './mini/compileScript' -import { compileDepStyles, initCompileStyles } from './mini/compileStyle' +import { build as buildMini } from './mini' import { IBuildOptions } from './util/types' +import { Builder } from '.' -const PLUGIN_ROOT = 'plugin/' -const DOC_ROOT = 'doc/' -const NPM_DIR = 'npm/' const PLUGIN_JSON = 'plugin.json' const PLUGIN_MOCK_JSON = 'plugin-mock.json' -let isCopyingFiles = {} - -export async function build (appPath: string, { watch, platform }: IBuildOptions) { +export async function build (appPath: string, { watch, platform }: IBuildOptions, builder: Builder) { switch (platform) { case BUILD_TYPES.WEAPP: - buildWxPlugin(appPath, { watch }) + await buildWxPlugin(appPath, { watch, type: BUILD_TYPES.WEAPP }, builder) break case BUILD_TYPES.ALIPAY: - await buildWeapp(appPath, { watch, adapter: BUILD_TYPES.ALIPAY }) - buildAlipayPlugin() + await buildAlipayPlugin(appPath, { watch, type: BUILD_TYPES.ALIPAY }, builder) break default: console.log(chalk.red('输入插件类型错误,目前只支持 weapp/alipay 插件类型')) @@ -60,354 +31,16 @@ export async function build (appPath: string, { watch, platform }: IBuildOptions } } -function compilePluginJson (pluginJson, pluginPath) { - if (typeof pluginJson.main === 'string') { - pluginJson.main = pluginJson.main.replace(/\.tsx$|\.ts$/, '.js') - } - fs.writeJSONSync(pluginPath, pluginJson) -} - -function wxPluginWatchFiles () { - console.log() - console.log(chalk.gray('监听文件修改中...')) - console.log() - initCompileScripts() - initCompileStyles() - isCopyingFiles = {} - - const { - appPath, - sourceDirName, - sourceDir, - outputDir, - outputFilesTypes, - entryFilePath, - entryFileName, - appConfig - } = getBuildData() - const pluginDir = path.join(sourceDir, PLUGIN_ROOT) - const pluginPath = path.join(appPath, PLUGIN_ROOT) - const docDir = path.join(pluginDir, DOC_ROOT) - const docPath = path.join(appPath, DOC_ROOT) - - const watcher = chokidar.watch(sourceDir, { - ignored: /(^|[/\\])\../, - persistent: true, - ignoreInitial: true - }) - watcher - .on('addDir', dirPath => { - console.log(dirPath) - }) - .on('add', filePath => { - console.log(filePath) - }) - .on('change', async filePath => { - let outputFilePath - if (filePath.includes(docDir)) { - outputFilePath = filePath.replace(docDir, docPath) - } else if (filePath.includes(pluginDir)) { - outputFilePath = filePath.replace(pluginDir, pluginPath) - } else { - outputFilePath = filePath.replace(sourceDir, outputDir) - } - - const extname = path.extname(filePath) - if (REG_SCRIPT.test(extname) || REG_TYPESCRIPT.test(extname)) { - const pluginJsonPath = path.join(pluginDir, PLUGIN_JSON) - if (!fs.existsSync(pluginDir) || !fs.existsSync(pluginJsonPath)) { - return console.log(chalk.red('缺少 plugin.json!')) - } - const pluginJson = fs.readJSONSync(pluginJsonPath) - const pages = pluginJson.pages - const main = pluginJson.main || '' - - if (entryFilePath === filePath) { - Util.printLog(processTypeEnum.MODIFY, '入口文件', `${sourceDirName}/${entryFileName}.js`) - const config = await buildEntry() - // TODO 此处待优化 - if ((Util.checksum(JSON.stringify(config.pages)) !== Util.checksum(JSON.stringify(appConfig.pages))) || - (Util.checksum(JSON.stringify(config.subPackages || config['subpackages'] || {})) !== Util.checksum(JSON.stringify(appConfig.subPackages || appConfig['subpackages'] || {})))) { - setAppConfig(config) - await buildPages() - } - } else if (isWxPluginPage(Object.values(pages), filePath) || isFileToBePage(filePath)) { - filePath = filePath.replace(extname, '') - filePath = filePath.replace(path.join(sourceDir) + path.sep, '') - filePath = filePath.split(path.sep).join('/') - Util.printLog(processTypeEnum.MODIFY, '页面文件', `${sourceDirName}/${filePath}`) - await buildSinglePage(filePath) - } else if (isComponentHasBeenBuilt(filePath)) { - let outputShowFilePath = filePath.replace(appPath + path.sep, '') - outputShowFilePath = outputShowFilePath.split(path.sep).join('/') - Util.printLog(processTypeEnum.MODIFY, '组件文件', outputShowFilePath) - deleteHasBeenBuiltComponent(filePath) - const componentsNamedMap = getComponentsNamedMap() - if (isWindows) { - await new Promise((resolve, reject) => { - setTimeout(async () => { - await buildSingleComponent(Object.assign({ - path: filePath - }, componentsNamedMap[filePath])) - resolve() - }, 300) - }) - } else { - await buildSingleComponent(Object.assign({ - path: filePath - }, componentsNamedMap[filePath])) - } - } else { - const dependencyTree = getDependencyTree() - let isImported = false - dependencyTree.forEach(dependencyTreeItem => { - const scripts = dependencyTreeItem.script || [] - if (scripts.indexOf(filePath) >= 0) { - isImported = true - } - }) - - let modifySource = filePath.replace(appPath + path.sep, '') - modifySource = modifySource.split(path.sep).join('/') - - if (isImported || filePath.includes(path.join(pluginDir, main))) { - Util.printLog(processTypeEnum.MODIFY, 'JS文件', modifySource) - await Promise.all(compileDepScripts([filePath], true, true)) - } else { - Util.printLog(processTypeEnum.WARNING, 'JS文件', `${modifySource} 没有被引用到,不会被编译`) - } - } - } else if (REG_STYLE.test(extname)) { - const dependencyTree = getDependencyTree() - const includeStyleJSPath: { filePath: string, styles: any[] }[] = [] - dependencyTree.forEach((dependencyTreeItem, key) => { - const styles = dependencyTreeItem['style'] || [] - styles.forEach(item => { - if (item === filePath) { - includeStyleJSPath.push({ - filePath: key, - styles - }) - } - }) - }) - - if (includeStyleJSPath.length) { - await Promise.all(includeStyleJSPath.map(async item => { - let outputWXSSPath = item.filePath.replace(path.extname(item.filePath), outputFilesTypes.STYLE) - let modifySource = outputWXSSPath.replace(appPath + path.sep, '') - modifySource = modifySource.split(path.sep).join('/') - Util.printLog(processTypeEnum.MODIFY, '样式文件', modifySource) - - outputWXSSPath = outputWXSSPath.replace(sourceDir, outputDir) - if (isWindows) { - await new Promise((resolve, reject) => { - setTimeout(async () => { - await compileDepStyles(outputWXSSPath, item.styles) - resolve() - }, 300) - }) - } else { - await compileDepStyles(outputWXSSPath, item.styles) - } - - let modifyOutput = outputWXSSPath.replace(appPath + path.sep, '') - modifyOutput = modifyOutput.split(path.sep).join('/') - Util.printLog(processTypeEnum.GENERATE, '样式文件', modifyOutput) - })) - } else { - let outputWXSSPath = filePath.replace(path.extname(filePath), outputFilesTypes.STYLE) - let modifySource = outputWXSSPath.replace(appPath + path.sep, '') - modifySource = modifySource.split(path.sep).join('/') - Util.printLog(processTypeEnum.MODIFY, '样式文件', modifySource) - outputWXSSPath = outputWXSSPath.replace(sourceDir, outputDir) - if (isWindows) { - await new Promise((resolve, reject) => { - setTimeout(async () => { - await compileDepStyles(outputWXSSPath, [filePath]) - resolve() - }, 300) - }) - } else { - await compileDepStyles(outputWXSSPath, [filePath]) - } - let modifyOutput = outputWXSSPath.replace(appPath + path.sep, '') - modifyOutput = modifyOutput.split(path.sep).join('/') - Util.printLog(processTypeEnum.GENERATE, '样式文件', modifyOutput) - } - } else { - if (isCopyingFiles[outputFilePath]) return - isCopyingFiles[outputFilePath] = true - - let modifyOutput = outputFilePath.replace(appPath + path.sep, '') - modifyOutput = modifyOutput.split(path.sep).join('/') - Util.printLog(processTypeEnum.COPY, '文件', modifyOutput) - - if (!fs.existsSync(filePath)) { - let modifySrc = filePath.replace(appPath + path.sep, '') - modifySrc = modifySrc.split(path.sep).join('/') - Util.printLog(processTypeEnum.ERROR, '文件', `${modifySrc} 不存在`) - } else { - fs.ensureDir(path.dirname(outputFilePath)) - if (filePath === outputFilePath) { - return - } - const pluginJsonPath = path.join(sourceDir, PLUGIN_ROOT, PLUGIN_JSON) - if (filePath === pluginJsonPath) { - compilePluginJson(fs.readJSONSync(filePath), outputFilePath) - } else { - fs.copySync(filePath, outputFilePath) - } - } - } - - // 如果 output/plugin 里有新编译出的文件, - // 先把 js 里对 npm 的引用修改,然后把所有文件迁移到插件目录 - // 最后删除 output/plugin - const names = glob.sync(`${outputDir}/${PLUGIN_ROOT}/**/*`) - if (names.length) { - const jsNames = glob.sync(`${outputDir}/${PLUGIN_ROOT}/{,!(npm)/**/}?(*.js|*.json)`) - const ioPromises = jsNames.map(async name => { - const content = fs.readFileSync(name).toString() - - let isShouldBeWritten - let replacement = content.replace(/['|"]((\.\.\/)+)npm\/.+?['|"]/g, (str, $1) => { - isShouldBeWritten = true - return $1 === '../' ? str.replace('../', './') : str.replace('../', '') - }) - - const REG_PLUGIN_DEPS = RegExp(`['|"](/${PLUGIN_ROOT}.+)['|"]`, 'g') - replacement = replacement.replace(REG_PLUGIN_DEPS, (str, $1) => { - if (REG_FONT.test($1) || REG_IMAGE.test($1) || REG_MEDIA.test($1)) { - isShouldBeWritten = true - return str.replace(RegExp(`^['|"]/${PLUGIN_ROOT}`, 'g'), str => str.replace(`${PLUGIN_ROOT}`, '')) - } - return str - }) - - if (isShouldBeWritten) await fs.writeFile(name, replacement) - }) - await Promise.all(ioPromises) - - await Promise.all(names.map(async from => { - from = path.join(from) - if (fs.existsSync(from) && fs.statSync(from).isFile()) { - const to = from.replace(outputDir, appPath) - fs.ensureDirSync(path.dirname(to)) - await fs.copyFile(from, to) - } - })) - const tempPluginPath = path.join(outputDir, PLUGIN_ROOT) - Util.emptyDirectory(tempPluginPath) - fs.rmdirSync(tempPluginPath) - } - // 迁移 npm 到 plugin 目录 - Util.emptyDirectory(path.join(pluginPath, NPM_DIR)) - // fs.rmdirSync(tempPluginPath) - await fs.copy(path.join(outputDir, NPM_DIR), path.join(pluginPath, NPM_DIR)) - - initCompileScripts() - initCompileStyles() - isCopyingFiles = {} - }) -} - -function isWxPluginPage (pages, filePath) { - return pages.findIndex(page => filePath.includes(path.join(page))) >= 0 -} - -async function buildWxPlugin (appPath, { watch }) { - const { - sourceDir, - outputDir - } = setBuildData(appPath, BUILD_TYPES.WEAPP) - const pluginDir = path.join(sourceDir, PLUGIN_ROOT) - const pluginPath = path.join(appPath, PLUGIN_ROOT) - const docDir = path.join(pluginDir, DOC_ROOT) - const docPath = path.join(appPath, DOC_ROOT) - - setIsProduction(process.env.NODE_ENV === 'production' || !watch) - - fs.existsSync(pluginPath) && Util.emptyDirectory(pluginPath) - fs.existsSync(docPath) && Util.emptyDirectory(docPath) - // 编译调试项目 - await buildWeapp(appPath, { adapter: BUILD_TYPES.WEAPP, envHasBeenSet: true }) - - const pluginJsonPath = path.join(pluginDir, PLUGIN_JSON) - if (!fs.existsSync(pluginDir) || !fs.existsSync(pluginJsonPath)) { - return console.log(chalk.red('缺少 plugin.json!')) - } - const pluginJson = fs.readJSONSync(pluginJsonPath) - const components = pluginJson.publicComponents - const pages: { [key: string]: any } = pluginJson.pages - const main = pluginJson.main - - // 编译插件页面 - if (pages && Object.keys(pages).length) { - Util.printLog(processTypeEnum.COMPILE, '插件页面') - const pagesPromises = Object.values(pages).map(page => buildSinglePage(path.join(PLUGIN_ROOT, page))) - await Promise.all(pagesPromises) - } - - // 编译插件组件 - if (components && Object.keys(components).length) { - Util.printLog(processTypeEnum.COMPILE, '插件组件') - const componentList: any[] = [] - for (const component in components) { - const componentPath = components[component] - componentList.push({ - path: /^(\.|\/)/.test(componentPath) ? componentPath : '.' + path.sep + componentPath, - name: component, - type: 'default' - }) - } - const realComponentsPathList = getRealComponentsPathList(pluginJsonPath, componentList) - await buildDepComponents(realComponentsPathList) - } - - // 编译插件 main.js - if (main) { - Util.printLog(processTypeEnum.COMPILE, '插件 JS') - await Promise.all(compileDepScripts([path.join(pluginDir, main)], true, true)) - } - - // 把 plugin 目录挪到根目录 - await fs.move(path.join(outputDir, PLUGIN_ROOT), pluginPath) - // 把 npm 拷贝一份到 plugin 目录 - await fs.copy(path.join(outputDir, NPM_DIR), path.join(pluginPath, NPM_DIR)) - // 把 doc 目录拷贝到根目录 - fs.existsSync(docDir) && fs.copySync(docDir, docPath) - // 拷贝 plugin.json - compilePluginJson(pluginJson, path.join(pluginPath, PLUGIN_JSON)) - - // plugin 文件夹内对 npm 的引用路径修改 - const names = glob.sync('plugin/{,!(npm)/**/}?(*.js|*.json)') - const ioPromises = names.map(name => { - const content = fs.readFileSync(name).toString() - - let isShouldBeWritten - let replacement = content.replace(/['|"]((\.\.\/)+)npm\/.+?['|"]/g, (str, $1) => { - isShouldBeWritten = true - return $1 === '../' ? str.replace('../', './') : str.replace('../', '') - }) - - const REG_PLUGIN_DEPS = RegExp(`['|"](/${PLUGIN_ROOT}.+?)['|"]`, 'g') - replacement = replacement.replace(REG_PLUGIN_DEPS, (str, $1) => { - if (REG_FONT.test($1) || REG_IMAGE.test($1) || REG_MEDIA.test($1)) { - isShouldBeWritten = true - return str.replace(RegExp(`^['|"]/${PLUGIN_ROOT}`, 'g'), str => str.replace(`${PLUGIN_ROOT}`, '')) - } - return str - }) - - if (isShouldBeWritten) fs.writeFileSync(path.join(appPath, name), replacement) - }) - await Promise.all(ioPromises) - - watch && wxPluginWatchFiles() +async function buildWxPlugin (appPath, { watch, type }, builder) { + await buildMini(appPath, { watch, type: BUILD_TYPES.PLUGIN }, null, builder) + const { outputDirName } = getBuildData() + await buildMini(appPath, { watch, type }, { + outputDirName: `${outputDirName}/miniprogram` + }, builder) } -function buildAlipayPlugin () { +async function buildAlipayPlugin (appPath, { watch, type }, builder) { + await buildMini(appPath, { watch, type }, null, builder) const { sourceDir, outputDir diff --git a/packages/taro-cli/src/quickapp/template-rewriter.ts b/packages/taro-cli/src/quickapp/template-rewriter.ts deleted file mode 100644 index abc148762f47..000000000000 --- a/packages/taro-cli/src/quickapp/template-rewriter.ts +++ /dev/null @@ -1,13 +0,0 @@ -import parseXml from './template/parser' -import rewriteNode from './template/node' -import serialize from './template/serialize' - -export default function rewriterTemplate(code : string): string { - // 解析Code - const viewNodes = parseXml(`${code}`).children - // 解析视图组件 - const retNodes = rewriteNode(viewNodes) - // 生成xml代码 - const templateCode = serialize(retNodes) - return templateCode -} \ No newline at end of file diff --git a/packages/taro-cli/src/ui/common.ts b/packages/taro-cli/src/ui/common.ts index a2f39a7f8172..41f6e1b5a916 100644 --- a/packages/taro-cli/src/ui/common.ts +++ b/packages/taro-cli/src/ui/common.ts @@ -1,10 +1,12 @@ +import * as path from 'path' +import * as fs from 'fs-extra' + import * as t from 'babel-types' import * as glob from 'glob' import traverse from 'babel-traverse' -import * as path from 'path' -import * as wxTransformer from '@tarojs/transformer-wx' import generate from 'babel-generator' -import * as fs from 'fs-extra' +import * as wxTransformer from '@tarojs/transformer-wx' + import { IBuildData } from './ui.types' import { cssImports, printLog, resolveScriptPath, resolveStylePath, isNpmPkg } from '../util' import { processTypeEnum, REG_STYLE, REG_TYPESCRIPT, REG_SCRIPT, REG_JSON, REG_FONT, REG_IMAGE, REG_MEDIA, CSS_EXT } from '../util/constants' diff --git a/packages/taro-cli/src/ui/h5.ts b/packages/taro-cli/src/ui/h5.ts index c80faa65b363..e2fe99225246 100644 --- a/packages/taro-cli/src/ui/h5.ts +++ b/packages/taro-cli/src/ui/h5.ts @@ -25,8 +25,8 @@ async function buildForH5 (uiIndex = 'index', buildData: IBuildData) { } async function buildH5Script (buildData: IBuildData) { - const {appPath, projectConfig, entryFileName, sourceDirName, tempPath} = buildData - let {outputDirName} = buildData + const { appPath, projectConfig, entryFileName, sourceDirName, tempPath } = buildData + let { outputDirName } = buildData const h5Config: IH5BuildConfig = Object.assign({}, projectConfig.h5) const entryFile = path.basename(entryFileName, path.extname(entryFileName)) + '.js' outputDirName = `${outputDirName}/${H5_OUTPUT_NAME}` diff --git a/packages/taro-cli/src/ui/index.ts b/packages/taro-cli/src/ui/index.ts index 33d855ebe4b5..7b1651f4a8d3 100644 --- a/packages/taro-cli/src/ui/index.ts +++ b/packages/taro-cli/src/ui/index.ts @@ -17,7 +17,7 @@ import { BUILD_TYPES, REG_STYLE } from '../util/constants' -import { IBuildConfig } from '../util/types' +import { IBuildOptions } from '../util/types' import { setBuildData as setMiniBuildData } from '../mini/helper' import { IBuildData } from './ui.types' import { @@ -244,7 +244,7 @@ function watchFiles () { }) } -export async function build (appPath, {watch, uiIndex}: IBuildConfig) { +export async function build (appPath, {watch, uiIndex}: IBuildOptions) { setBuildData(appPath, uiIndex) setMiniBuildData(appPath, BUILD_TYPES.WEAPP) setMiniBuildData(appPath, BUILD_TYPES.QUICKAPP) diff --git a/packages/taro-cli/src/ui/rn.ts b/packages/taro-cli/src/ui/rn.ts index ca6bb0d801cc..c994e3e71b55 100644 --- a/packages/taro-cli/src/ui/rn.ts +++ b/packages/taro-cli/src/ui/rn.ts @@ -1,12 +1,13 @@ -import { IBuildData } from './ui.types' import * as path from 'path' -import { analyzeFiles, analyzeStyleFilesImport, copyFileToDist, RN_OUTPUT_NAME, parseEntryAst } from './common' -import { printLog, resolveScriptPath } from '../util' import * as fs from 'fs-extra' import * as wxTransformer from '@tarojs/transformer-wx' +import chalk from 'chalk' + import { processTypeEnum, REG_TYPESCRIPT } from '../util/constants' import { Compiler as RNCompiler } from '../rn' -import chalk from 'chalk' +import { analyzeFiles, analyzeStyleFilesImport, copyFileToDist, RN_OUTPUT_NAME, parseEntryAst } from './common' +import { printLog, resolveScriptPath } from '../util' +import { IBuildData } from './ui.types' export async function buildForRN (uiIndex = 'index', buildData) { const {appPath} = buildData diff --git a/packages/taro-cli/src/ui/ui.types.ts b/packages/taro-cli/src/ui/ui.types.ts index 3ab3cd7c407a..909e49815cdc 100644 --- a/packages/taro-cli/src/ui/ui.types.ts +++ b/packages/taro-cli/src/ui/ui.types.ts @@ -1,4 +1,4 @@ -import { IH5Config, IProjectConfig } from '../util/types' +import { IProjectConfig, IH5Config } from '@tarojs/taro/types/compile' export interface IBuildData { appPath: string, diff --git a/packages/taro-cli/src/ui/weapp.ts b/packages/taro-cli/src/ui/weapp.ts index 23575e6a2807..49cfde0b6cd2 100644 --- a/packages/taro-cli/src/ui/weapp.ts +++ b/packages/taro-cli/src/ui/weapp.ts @@ -1,9 +1,9 @@ import chalk from 'chalk' import * as fs from 'fs-extra' import * as path from 'path' +import * as wxTransformer from '@tarojs/transformer-wx' import { processTypeEnum, REG_TYPESCRIPT } from '../util/constants' -import * as wxTransformer from '@tarojs/transformer-wx' import { printLog } from '../util' import { analyzeFiles, parseEntryAst, WEAPP_OUTPUT_NAME, copyFileToDist, copyAllInterfaceFiles } from './common' import { IBuildData } from './ui.types' diff --git a/packages/taro-mini-runner/package.json b/packages/taro-mini-runner/package.json index a5313131a103..350355b94671 100644 --- a/packages/taro-mini-runner/package.json +++ b/packages/taro-mini-runner/package.json @@ -1,6 +1,6 @@ { "name": "@tarojs/mini-runner", - "version": "1.3.18", + "version": "1.3.19", "description": "Mini app runner for taro", "main": "index.js", "scripts": { @@ -32,8 +32,8 @@ }, "homepage": "https://github.com/NervJS/taro#readme", "dependencies": { - "@tarojs/taro": "1.3.18", - "@tarojs/transformer-wx": "1.3.18", + "@tarojs/taro": "1.3.19", + "@tarojs/transformer-wx": "1.3.19", "babel-core": "^6.26.3", "babel-generator": "^6.26.1", "babel-loader": "^8.0.6", diff --git a/packages/taro-mini-runner/src/index.ts b/packages/taro-mini-runner/src/index.ts index feb45ea71f84..57ac020bbba4 100644 --- a/packages/taro-mini-runner/src/index.ts +++ b/packages/taro-mini-runner/src/index.ts @@ -1,6 +1,7 @@ import * as webpack from 'webpack' import { IBuildConfig } from './utils/types' +import { BUILD_TYPES } from './utils/constants' import { printBuildError, bindProdLogger, bindDevLogger } from './utils/logHelper' import buildConf from './webpack/build.conf' @@ -13,6 +14,11 @@ const customizeChain = (chain, customizeFunc: Function) => { export default function build (appPath: string, config: IBuildConfig, mainBuilder) { const mode = config.isWatch ? 'development' : 'production' return new Promise((resolve, reject) => { + const { buildAdapter } = config + if (buildAdapter === BUILD_TYPES.PLUGIN) { + config.buildAdapter = BUILD_TYPES.WEAPP + config.isBuildPlugin = true + } const webpackChain = buildConf(appPath, mode, config) customizeChain(webpackChain, config.webpackChain) diff --git a/packages/taro-mini-runner/src/plugins/MiniPlugin.ts b/packages/taro-mini-runner/src/plugins/MiniPlugin.ts index dceb7a3cdbac..0e4a46cc7205 100644 --- a/packages/taro-mini-runner/src/plugins/MiniPlugin.ts +++ b/packages/taro-mini-runner/src/plugins/MiniPlugin.ts @@ -34,7 +34,9 @@ interface IMiniPluginOptions { outputDir: string, quickappJSON?: any, designWidth: number, - commonChunks: string[] + commonChunks: string[], + pluginConfig?: object, + isBuildPlugin: boolean } export interface ITaroFileInfo { @@ -145,7 +147,8 @@ export default class MiniPlugin { sourceDir: '', outputDir: '', designWidth: 750, - commonChunks: ['runtime', 'vendors'] + commonChunks: ['runtime', 'vendors'], + isBuildPlugin: false }) this.sourceDir = this.options.sourceDir this.outputDir = this.options.outputDir @@ -200,7 +203,8 @@ export default class MiniPlugin { new TaroLoadChunksPlugin({ commonChunks: this.options.commonChunks, - buildAdapter: this.options.buildAdapter + buildAdapter: this.options.buildAdapter, + isBuildPlugin: this.options.isBuildPlugin }).apply(compiler) new TaroNormalModulesPlugin().apply(compiler) @@ -214,10 +218,16 @@ export default class MiniPlugin { } getAppEntry (compiler) { + const { entry } = compiler.options + if (this.options.isBuildPlugin) { + const entryCopy = Object.assign({}, entry) + compiler.options.entry = {} + return entryCopy + } if (this.options.appEntry) { + compiler.options.entry = {} return this.options.appEntry } - const { entry } = compiler.options function getEntryPath (entry) { const app = entry['app'] if (Array.isArray(app)) { @@ -409,6 +419,81 @@ export default class MiniPlugin { ]) } + getPluginFiles (compiler) { + const fileList = new Set() + const { pluginConfig, buildAdapter } = this.options + let normalFiles = new Set() + Object.keys(this.appEntry).forEach(key => { + const filePath = this.appEntry[key][0] + const code = fs.readFileSync(filePath).toString() + if (isFileToBeTaroComponent(code, filePath, buildAdapter)) { + if (pluginConfig) { + fileList.add({ + name: key, + path: filePath, + isNative: false + }) + let isPage = false + let isComponent = false + Object.keys(pluginConfig).forEach(pluginKey => { + if (pluginKey === 'pages') { + Object.keys(pluginConfig[pluginKey]).forEach(pageKey => { + if (`plugin/${pluginConfig[pluginKey][pageKey]}` === key) { + isPage = true + } + }) + } + if (pluginKey === 'publicComponents') { + Object.keys(pluginConfig[pluginKey]).forEach(pageKey => { + if (`plugin/${pluginConfig[pluginKey][pageKey]}` === key) { + isComponent = true + } + }) + } + }) + if (isPage) { + this.pages.add({ + name: key, + path: filePath, + isNative: false + }) + this.getComponents(fileList, isPage) + } else if (isComponent) { + this.components.add({ + name: key, + path: filePath, + isNative: false + }) + this.getComponents(fileList, false) + } else { + normalFiles.add({ + name: key, + path: filePath, + isNative: true + }) + } + } + } + }) + normalFiles.forEach(item => { + this.addEntry(compiler, item.path, item.name, PARSE_AST_TYPE.NORMAL) + }) + this.pages.forEach(item => { + if (item.isNative) { + this.addEntry(compiler, item.path, item.name, PARSE_AST_TYPE.NORMAL) + } else { + this.addEntry(compiler, item.path, item.name, PARSE_AST_TYPE.PAGE) + } + }) + this.components.forEach(item => { + if (item.isNative) { + this.addEntry(compiler, item.path, item.name, PARSE_AST_TYPE.NORMAL) + } else { + this.addEntry(compiler, item.path, item.name, PARSE_AST_TYPE.COMPONENT) + } + }) + } + isNativePageORComponent (templatePath, jsContent) { return fs.existsSync(templatePath) && jsContent.indexOf(taroJsFramework) < 0 } @@ -680,9 +765,13 @@ export default class MiniPlugin { } run (compiler: webpack.Compiler) { - this.getPages(compiler) - this.getComponents(this.pages, true) - this.addEntries(compiler) + if (!this.options.isBuildPlugin) { + this.getPages(compiler) + this.getComponents(this.pages, true) + this.addEntries(compiler) + } else { + this.getPluginFiles(compiler) + } this.transferFileContent(compiler) } diff --git a/packages/taro-mini-runner/src/plugins/TaroLoadChunksPlugin.ts b/packages/taro-mini-runner/src/plugins/TaroLoadChunksPlugin.ts index e7aa2eb57ee7..d93dc4cc1caf 100644 --- a/packages/taro-mini-runner/src/plugins/TaroLoadChunksPlugin.ts +++ b/packages/taro-mini-runner/src/plugins/TaroLoadChunksPlugin.ts @@ -11,16 +11,19 @@ const PLUGIN_NAME = 'TaroLoadChunksPlugin' interface IOptions { commonChunks: string[], - buildAdapter: BUILD_TYPES + buildAdapter: BUILD_TYPES, + isBuildPlugin: boolean } export default class TaroLoadChunksPlugin { commonChunks: string[] buildAdapter: BUILD_TYPES + isBuildPlugin: boolean constructor (options: IOptions) { this.commonChunks = options.commonChunks this.buildAdapter = options.buildAdapter + this.isBuildPlugin = options.isBuildPlugin } apply (compiler: webpack.Compiler) { @@ -31,7 +34,10 @@ export default class TaroLoadChunksPlugin { }) compilation.chunkTemplate.hooks.renderWithEntry.tap(PLUGIN_NAME, (modules, chunk) => { if (chunk.entryModule) { - if (chunk.entryModule.miniType === PARSE_AST_TYPE.ENTRY) { + if (this.isBuildPlugin) { + const id = chunk.id + return addRequireToSource(id, modules, commonChunks) + } else if (chunk.entryModule.miniType === PARSE_AST_TYPE.ENTRY) { compilation.hooks.afterOptimizeAssets.tap(PLUGIN_NAME, assets => { const files = chunk.files files.forEach(item => { @@ -50,30 +56,27 @@ export default class TaroLoadChunksPlugin { } }) }) - const source = new ConcatSource() const name = chunk.name - commonChunks.forEach(chunkItem => { - source.add(`require(${JSON.stringify(promoteRelativePath(path.relative(name, chunkItem.name)))});\n`) - }) - source.add('\n') - source.add(modules) - source.add(';') - return source - } else if (this.buildAdapter === BUILD_TYPES.QUICKAPP && + return addRequireToSource(name, modules, commonChunks) + } else if ((this.buildAdapter === BUILD_TYPES.QUICKAPP) && (chunk.entryModule.miniType === PARSE_AST_TYPE.PAGE || chunk.entryModule.miniType === PARSE_AST_TYPE.COMPONENT)) { - const source = new ConcatSource() const id = chunk.id - commonChunks.forEach(chunkItem => { - source.add(`require(${JSON.stringify(promoteRelativePath(path.relative(id, chunkItem.name)))});\n`) - }) - source.add('\n') - source.add(modules) - source.add(';') - return source + return addRequireToSource(id, modules, commonChunks) } } }) }) } } + +function addRequireToSource (id, modules, commonChunks) { + const source = new ConcatSource() + commonChunks.forEach(chunkItem => { + source.add(`require(${JSON.stringify(promoteRelativePath(path.relative(id, chunkItem.name)))});\n`) + }) + source.add('\n') + source.add(modules) + source.add(';') + return source +} diff --git a/packages/taro-cli/src/quickapp/style-rewriter.ts b/packages/taro-mini-runner/src/quickapp/style-rewriter.ts similarity index 100% rename from packages/taro-cli/src/quickapp/style-rewriter.ts rename to packages/taro-mini-runner/src/quickapp/style-rewriter.ts diff --git a/packages/taro-cli/src/quickapp/style/declaration/animation/index.ts b/packages/taro-mini-runner/src/quickapp/style/declaration/animation/index.ts similarity index 100% rename from packages/taro-cli/src/quickapp/style/declaration/animation/index.ts rename to packages/taro-mini-runner/src/quickapp/style/declaration/animation/index.ts diff --git a/packages/taro-cli/src/quickapp/style/declaration/background/index.ts b/packages/taro-mini-runner/src/quickapp/style/declaration/background/index.ts similarity index 100% rename from packages/taro-cli/src/quickapp/style/declaration/background/index.ts rename to packages/taro-mini-runner/src/quickapp/style/declaration/background/index.ts diff --git a/packages/taro-cli/src/quickapp/style/declaration/border/index.ts b/packages/taro-mini-runner/src/quickapp/style/declaration/border/index.ts similarity index 100% rename from packages/taro-cli/src/quickapp/style/declaration/border/index.ts rename to packages/taro-mini-runner/src/quickapp/style/declaration/border/index.ts diff --git a/packages/taro-cli/src/quickapp/style/declaration/box/index.ts b/packages/taro-mini-runner/src/quickapp/style/declaration/box/index.ts similarity index 100% rename from packages/taro-cli/src/quickapp/style/declaration/box/index.ts rename to packages/taro-mini-runner/src/quickapp/style/declaration/box/index.ts diff --git a/packages/taro-cli/src/quickapp/style/declaration/color/index.ts b/packages/taro-mini-runner/src/quickapp/style/declaration/color/index.ts similarity index 100% rename from packages/taro-cli/src/quickapp/style/declaration/color/index.ts rename to packages/taro-mini-runner/src/quickapp/style/declaration/color/index.ts diff --git a/packages/taro-cli/src/quickapp/style/declaration/component/index.ts b/packages/taro-mini-runner/src/quickapp/style/declaration/component/index.ts similarity index 100% rename from packages/taro-cli/src/quickapp/style/declaration/component/index.ts rename to packages/taro-mini-runner/src/quickapp/style/declaration/component/index.ts diff --git a/packages/taro-cli/src/quickapp/style/declaration/dimension/index.ts b/packages/taro-mini-runner/src/quickapp/style/declaration/dimension/index.ts similarity index 100% rename from packages/taro-cli/src/quickapp/style/declaration/dimension/index.ts rename to packages/taro-mini-runner/src/quickapp/style/declaration/dimension/index.ts diff --git a/packages/taro-cli/src/quickapp/style/declaration/flexbox/index.ts b/packages/taro-mini-runner/src/quickapp/style/declaration/flexbox/index.ts similarity index 100% rename from packages/taro-cli/src/quickapp/style/declaration/flexbox/index.ts rename to packages/taro-mini-runner/src/quickapp/style/declaration/flexbox/index.ts diff --git a/packages/taro-cli/src/quickapp/style/declaration/font/index.ts b/packages/taro-mini-runner/src/quickapp/style/declaration/font/index.ts similarity index 100% rename from packages/taro-cli/src/quickapp/style/declaration/font/index.ts rename to packages/taro-mini-runner/src/quickapp/style/declaration/font/index.ts diff --git a/packages/taro-cli/src/quickapp/style/declaration/index.ts b/packages/taro-mini-runner/src/quickapp/style/declaration/index.ts similarity index 100% rename from packages/taro-cli/src/quickapp/style/declaration/index.ts rename to packages/taro-mini-runner/src/quickapp/style/declaration/index.ts diff --git a/packages/taro-cli/src/quickapp/style/declaration/list/index.ts b/packages/taro-mini-runner/src/quickapp/style/declaration/list/index.ts similarity index 100% rename from packages/taro-cli/src/quickapp/style/declaration/list/index.ts rename to packages/taro-mini-runner/src/quickapp/style/declaration/list/index.ts diff --git a/packages/taro-cli/src/quickapp/style/declaration/margin/index.ts b/packages/taro-mini-runner/src/quickapp/style/declaration/margin/index.ts similarity index 100% rename from packages/taro-cli/src/quickapp/style/declaration/margin/index.ts rename to packages/taro-mini-runner/src/quickapp/style/declaration/margin/index.ts diff --git a/packages/taro-cli/src/quickapp/style/declaration/padding/index.ts b/packages/taro-mini-runner/src/quickapp/style/declaration/padding/index.ts similarity index 100% rename from packages/taro-cli/src/quickapp/style/declaration/padding/index.ts rename to packages/taro-mini-runner/src/quickapp/style/declaration/padding/index.ts diff --git a/packages/taro-cli/src/quickapp/style/declaration/position/index.ts b/packages/taro-mini-runner/src/quickapp/style/declaration/position/index.ts similarity index 100% rename from packages/taro-cli/src/quickapp/style/declaration/position/index.ts rename to packages/taro-mini-runner/src/quickapp/style/declaration/position/index.ts diff --git a/packages/taro-cli/src/quickapp/style/declaration/text/index.ts b/packages/taro-mini-runner/src/quickapp/style/declaration/text/index.ts similarity index 100% rename from packages/taro-cli/src/quickapp/style/declaration/text/index.ts rename to packages/taro-mini-runner/src/quickapp/style/declaration/text/index.ts diff --git a/packages/taro-cli/src/quickapp/style/declaration/transform/transform.ts b/packages/taro-mini-runner/src/quickapp/style/declaration/transform/transform.ts similarity index 100% rename from packages/taro-cli/src/quickapp/style/declaration/transform/transform.ts rename to packages/taro-mini-runner/src/quickapp/style/declaration/transform/transform.ts diff --git a/packages/taro-cli/src/quickapp/style/declaration/transition/index.ts b/packages/taro-mini-runner/src/quickapp/style/declaration/transition/index.ts similarity index 100% rename from packages/taro-cli/src/quickapp/style/declaration/transition/index.ts rename to packages/taro-mini-runner/src/quickapp/style/declaration/transition/index.ts diff --git a/packages/taro-cli/src/quickapp/style/declaration/visibility/index.ts b/packages/taro-mini-runner/src/quickapp/style/declaration/visibility/index.ts similarity index 100% rename from packages/taro-cli/src/quickapp/style/declaration/visibility/index.ts rename to packages/taro-mini-runner/src/quickapp/style/declaration/visibility/index.ts diff --git a/packages/taro-cli/src/quickapp/style/index.ts b/packages/taro-mini-runner/src/quickapp/style/index.ts similarity index 100% rename from packages/taro-cli/src/quickapp/style/index.ts rename to packages/taro-mini-runner/src/quickapp/style/index.ts diff --git a/packages/taro-cli/src/quickapp/style/selector/index.ts b/packages/taro-mini-runner/src/quickapp/style/selector/index.ts similarity index 100% rename from packages/taro-cli/src/quickapp/style/selector/index.ts rename to packages/taro-mini-runner/src/quickapp/style/selector/index.ts diff --git a/packages/taro-cli/src/quickapp/style/util.ts b/packages/taro-mini-runner/src/quickapp/style/util.ts similarity index 100% rename from packages/taro-cli/src/quickapp/style/util.ts rename to packages/taro-mini-runner/src/quickapp/style/util.ts diff --git a/packages/taro-mini-runner/src/quickapp/template-rewriter.ts b/packages/taro-mini-runner/src/quickapp/template-rewriter.ts new file mode 100644 index 000000000000..812410bae3bb --- /dev/null +++ b/packages/taro-mini-runner/src/quickapp/template-rewriter.ts @@ -0,0 +1,13 @@ +import parseXml from './template/parser' +import rewriteNode from './template/node' +import serialize from './template/serialize' + +export default function rewriterTemplate(code : string): string { + // 解析Code + const viewNodes = parseXml(`${code}`).children + // 解析视图组件 + const retNodes = rewriteNode(viewNodes) + // 生成xml代码 + const templateCode = serialize(retNodes) + return templateCode +} diff --git a/packages/taro-cli/src/quickapp/template/constant.ts b/packages/taro-mini-runner/src/quickapp/template/constant.ts similarity index 100% rename from packages/taro-cli/src/quickapp/template/constant.ts rename to packages/taro-mini-runner/src/quickapp/template/constant.ts diff --git a/packages/taro-cli/src/quickapp/template/node.ts b/packages/taro-mini-runner/src/quickapp/template/node.ts similarity index 100% rename from packages/taro-cli/src/quickapp/template/node.ts rename to packages/taro-mini-runner/src/quickapp/template/node.ts diff --git a/packages/taro-cli/src/quickapp/template/parser.ts b/packages/taro-mini-runner/src/quickapp/template/parser.ts similarity index 100% rename from packages/taro-cli/src/quickapp/template/parser.ts rename to packages/taro-mini-runner/src/quickapp/template/parser.ts diff --git a/packages/taro-cli/src/quickapp/template/serialize.ts b/packages/taro-mini-runner/src/quickapp/template/serialize.ts similarity index 100% rename from packages/taro-cli/src/quickapp/template/serialize.ts rename to packages/taro-mini-runner/src/quickapp/template/serialize.ts diff --git a/packages/taro-cli/src/quickapp/template/tag/index.ts b/packages/taro-mini-runner/src/quickapp/template/tag/index.ts similarity index 100% rename from packages/taro-cli/src/quickapp/template/tag/index.ts rename to packages/taro-mini-runner/src/quickapp/template/tag/index.ts diff --git a/packages/taro-cli/src/quickapp/template/tag/span/index.ts b/packages/taro-mini-runner/src/quickapp/template/tag/span/index.ts similarity index 100% rename from packages/taro-cli/src/quickapp/template/tag/span/index.ts rename to packages/taro-mini-runner/src/quickapp/template/tag/span/index.ts diff --git a/packages/taro-cli/src/quickapp/template/tag/taro-camera/index.ts b/packages/taro-mini-runner/src/quickapp/template/tag/taro-camera/index.ts similarity index 100% rename from packages/taro-cli/src/quickapp/template/tag/taro-camera/index.ts rename to packages/taro-mini-runner/src/quickapp/template/tag/taro-camera/index.ts diff --git a/packages/taro-cli/src/quickapp/template/tag/taro-canvas/index.ts b/packages/taro-mini-runner/src/quickapp/template/tag/taro-canvas/index.ts similarity index 100% rename from packages/taro-cli/src/quickapp/template/tag/taro-canvas/index.ts rename to packages/taro-mini-runner/src/quickapp/template/tag/taro-canvas/index.ts diff --git a/packages/taro-cli/src/quickapp/template/tag/taro-image/index.ts b/packages/taro-mini-runner/src/quickapp/template/tag/taro-image/index.ts similarity index 100% rename from packages/taro-cli/src/quickapp/template/tag/taro-image/index.ts rename to packages/taro-mini-runner/src/quickapp/template/tag/taro-image/index.ts diff --git a/packages/taro-cli/src/quickapp/template/tag/taro-input/index.ts b/packages/taro-mini-runner/src/quickapp/template/tag/taro-input/index.ts similarity index 100% rename from packages/taro-cli/src/quickapp/template/tag/taro-input/index.ts rename to packages/taro-mini-runner/src/quickapp/template/tag/taro-input/index.ts diff --git a/packages/taro-cli/src/quickapp/template/tag/taro-label/index.ts b/packages/taro-mini-runner/src/quickapp/template/tag/taro-label/index.ts similarity index 100% rename from packages/taro-cli/src/quickapp/template/tag/taro-label/index.ts rename to packages/taro-mini-runner/src/quickapp/template/tag/taro-label/index.ts diff --git a/packages/taro-cli/src/quickapp/template/tag/taro-map/index.ts b/packages/taro-mini-runner/src/quickapp/template/tag/taro-map/index.ts similarity index 100% rename from packages/taro-cli/src/quickapp/template/tag/taro-map/index.ts rename to packages/taro-mini-runner/src/quickapp/template/tag/taro-map/index.ts diff --git a/packages/taro-cli/src/quickapp/template/tag/taro-picker/index.ts b/packages/taro-mini-runner/src/quickapp/template/tag/taro-picker/index.ts similarity index 100% rename from packages/taro-cli/src/quickapp/template/tag/taro-picker/index.ts rename to packages/taro-mini-runner/src/quickapp/template/tag/taro-picker/index.ts diff --git a/packages/taro-cli/src/quickapp/template/tag/taro-textarea/index.ts b/packages/taro-mini-runner/src/quickapp/template/tag/taro-textarea/index.ts similarity index 100% rename from packages/taro-cli/src/quickapp/template/tag/taro-textarea/index.ts rename to packages/taro-mini-runner/src/quickapp/template/tag/taro-textarea/index.ts diff --git a/packages/taro-cli/src/quickapp/template/tag/taro-video/index.ts b/packages/taro-mini-runner/src/quickapp/template/tag/taro-video/index.ts similarity index 100% rename from packages/taro-cli/src/quickapp/template/tag/taro-video/index.ts rename to packages/taro-mini-runner/src/quickapp/template/tag/taro-video/index.ts diff --git a/packages/taro-cli/src/quickapp/template/tag/text/index.ts b/packages/taro-mini-runner/src/quickapp/template/tag/text/index.ts similarity index 100% rename from packages/taro-cli/src/quickapp/template/tag/text/index.ts rename to packages/taro-mini-runner/src/quickapp/template/tag/text/index.ts diff --git a/packages/taro-cli/src/quickapp/template/utils.ts b/packages/taro-mini-runner/src/quickapp/template/utils.ts similarity index 100% rename from packages/taro-cli/src/quickapp/template/utils.ts rename to packages/taro-mini-runner/src/quickapp/template/utils.ts diff --git a/packages/taro-mini-runner/src/utils/types.ts b/packages/taro-mini-runner/src/utils/types.ts index c4b5d8af72ee..41183312bad9 100644 --- a/packages/taro-mini-runner/src/utils/types.ts +++ b/packages/taro-mini-runner/src/utils/types.ts @@ -24,5 +24,6 @@ export interface IBuildConfig extends IProjectBaseConfig, IMiniAppConfig { port?: number, buildAdapter: BUILD_TYPES, nodeModulesPath: string, - quickappJSON: any + quickappJSON: any, + isBuildPlugin: boolean } diff --git a/packages/taro-mini-runner/src/webpack/build.conf.ts b/packages/taro-mini-runner/src/webpack/build.conf.ts index 11109bb13905..71d891cbfd3f 100644 --- a/packages/taro-mini-runner/src/webpack/build.conf.ts +++ b/packages/taro-mini-runner/src/webpack/build.conf.ts @@ -13,6 +13,7 @@ import { mergeOption, getMiniPlugin, getMiniCssExtractPlugin, + getEntry, } from './chain' import getBaseConf from './base.conf' import { BUILD_TYPES, PARSE_AST_TYPE, MINI_APP_FILES } from '../utils/constants' @@ -25,7 +26,6 @@ export default (appPath: string, mode, config: Partial): any => { const { buildAdapter = BUILD_TYPES.WEAPP, alias = emptyObj, - copy, entry = emptyObj, output = emptyObj, outputRoot = 'dist', @@ -55,15 +55,33 @@ export default (appPath: string, mode, config: Partial): any => { uglify } = config + let { copy } = config + const plugin: any = {} const minimizer: any[] = [] const sourceDir = path.join(appPath, sourceRoot) const outputDir = path.join(appPath, outputRoot) - + if (config.isBuildPlugin) { + const patterns = copy ? copy.patterns : [] + patterns.push({ + from: path.join(sourceRoot, 'plugin', 'doc'), + to: path.join(outputRoot, 'doc') + }) + patterns.push({ + from: path.join(sourceRoot, 'plugin', 'plugin.json'), + to: path.join(outputRoot, 'plugin', 'plugin.json') + }) + copy = Object.assign({}, copy, { patterns }) + } if (copy) { plugin.copyWebpackPlugin = getCopyWebpackPlugin({ copy, appPath }) } const constantsReplaceList = mergeOption([processEnvOption(env), defineConstants]) + const entryRes = getEntry({ + sourceDir, + entry, + isBuildPlugin: config.isBuildPlugin + }) plugin.definePlugin = getDefinePlugin([constantsReplaceList]) plugin.miniPlugin = getMiniPlugin({ sourceDir, @@ -72,7 +90,10 @@ export default (appPath: string, mode, config: Partial): any => { constantsReplaceList, nodeModulesPath, quickappJSON, - designWidth + designWidth, + pluginConfig: entryRes!.pluginConfig, + isBuildPlugin: !!config.isBuildPlugin, + commonChunks: !!config.isBuildPlugin ? ['plugin/runtime', 'plugin/vendors'] : ['runtime', 'vendors'] }) plugin.miniCssExtractPlugin = getMiniCssExtractPlugin([{ @@ -84,7 +105,6 @@ export default (appPath: string, mode, config: Partial): any => { ? false : true - const isUglifyEnabled = (uglify && uglify.enable === false) ? false : true @@ -105,11 +125,12 @@ export default (appPath: string, mode, config: Partial): any => { chain.merge({ mode, devtool: getDevtool(enableSourceMap), - entry, + entry: entryRes!.entry, output: getOutput(appPath, [{ outputRoot, publicPath: '/', buildAdapter, + isBuildPlugin: config.isBuildPlugin }, output]), target: Targets[buildAdapter], resolve: { alias }, @@ -137,13 +158,13 @@ export default (appPath: string, mode, config: Partial): any => { optimization: { minimizer, runtimeChunk: { - name: 'runtime' + name: !!config.isBuildPlugin ? 'plugin/runtime' : 'runtime' }, splitChunks: { chunks: 'all', maxInitialRequests: Infinity, minSize: 0, - name: 'vendors', + name: !!config.isBuildPlugin ? 'plugin/vendors' : 'vendors', cacheGroups: { vendors: { test (module) { diff --git a/packages/taro-mini-runner/src/webpack/chain.ts b/packages/taro-mini-runner/src/webpack/chain.ts index d6109337b519..cb3d687bfa14 100644 --- a/packages/taro-mini-runner/src/webpack/chain.ts +++ b/packages/taro-mini-runner/src/webpack/chain.ts @@ -1,3 +1,4 @@ +import * as fs from 'fs-extra' import * as path from 'path' import * as CopyWebpackPlugin from 'copy-webpack-plugin' @@ -9,12 +10,13 @@ import { mapKeys, pipe } from 'lodash/fp' import * as UglifyJsPlugin from 'uglifyjs-webpack-plugin' import * as webpack from 'webpack' import { PostcssOption, ICopyOptions, IPostcssOption } from '@tarojs/taro/types/compile' +import chalk from 'chalk' import { getPostcssPlugins } from './postcss.conf' import MiniPlugin from '../plugins/MiniPlugin' import { IOption } from '../utils/types' -import { recursiveMerge, isNodeModule } from '../utils' +import { recursiveMerge, isNodeModule, resolveScriptPath } from '../utils' import { REG_SASS, REG_LESS, @@ -149,7 +151,7 @@ export const getCopyWebpackPlugin = ({ copy, appPath }: { return partial(getPlugin, CopyWebpackPlugin)(args) } -export const getMiniPlugin = (args) => { +export const getMiniPlugin = args => { return partial(getPlugin, MiniPlugin)([args]) } @@ -339,7 +341,47 @@ export const getModule = (appPath: string, { return { rule } } -export function getOutput (appPath: string, [{ outputRoot, publicPath, buildAdapter }, customOutput]) { +export const getEntry = ({ + sourceDir, + entry, + isBuildPlugin +}) => { + if (!isBuildPlugin) { + return { + entry + } + } + const pluginDir = path.join(sourceDir, 'plugin') + if (!fs.existsSync(pluginDir)) { + console.log(chalk.red('插件目录不存在,请检查!')) + return + } + const pluginConfigPath = path.join(pluginDir, 'plugin.json') + if (!fs.existsSync(pluginConfigPath)) { + console.log(chalk.red('缺少插件配置文件,请检查!')) + return + } + const pluginConfig = fs.readJSONSync(pluginConfigPath) + const entryObj = {} + Object.keys(pluginConfig).forEach(key => { + if (key === 'main') { + const filePath = path.join(pluginDir, pluginConfig[key]) + const fileName = path.basename(filePath).replace(path.extname(filePath), '') + entryObj[`plugin/${fileName}`] = [resolveScriptPath(filePath.replace(path.extname(filePath), ''))] + } else if (key === 'publicComponents' || key === 'pages') { + Object.keys(pluginConfig[key]).forEach(subKey => { + const filePath = path.join(pluginDir, pluginConfig[key][subKey]) + entryObj[`plugin/${pluginConfig[key][subKey]}`] = [resolveScriptPath(filePath.replace(path.extname(filePath), ''))] + }) + } + }) + return { + entry: entryObj, + pluginConfig + } +} + +export function getOutput (appPath: string, [{ outputRoot, publicPath, buildAdapter, isBuildPlugin }, customOutput]) { return { path: path.join(appPath, outputRoot), publicPath, diff --git a/packages/taro-webpack-runner/src/index.ts b/packages/taro-webpack-runner/src/index.ts index f55c0e1f2825..3e7bd7adb82e 100644 --- a/packages/taro-webpack-runner/src/index.ts +++ b/packages/taro-webpack-runner/src/index.ts @@ -134,7 +134,7 @@ const buildDev = async (appPath: string, config: BuildConfig): Promise => { } export default async (appPath: string, config: BuildConfig): Promise => { - const newConfig: BuildConfig = await makeConfig(config); + const newConfig: BuildConfig = await makeConfig(config) if (newConfig.isWatch) { try { await buildDev(appPath, newConfig)