From 09f3f4129da6843012104a6c4386864e1f7f560b Mon Sep 17 00:00:00 2001 From: luckyadam Date: Mon, 17 Jun 2019 22:13:01 +0800 Subject: [PATCH] =?UTF-8?q?feat(cli):=20=E5=80=9F=E5=8A=A9=20tapable=20?= =?UTF-8?q?=E6=94=B9=E9=80=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/taro-cli/bin/taro-build | 9 +- packages/taro-cli/src/build.ts | 210 ++++++++++++-------------- packages/taro-cli/src/index.ts | 6 +- packages/taro-cli/src/mini/webpack.ts | 11 +- packages/taro-cli/src/util/types.ts | 11 +- 5 files changed, 123 insertions(+), 124 deletions(-) diff --git a/packages/taro-cli/bin/taro-build b/packages/taro-cli/bin/taro-build index 08d2ea63afc2..e44bfb287db8 100755 --- a/packages/taro-cli/bin/taro-build +++ b/packages/taro-cli/bin/taro-build @@ -5,7 +5,7 @@ const program = require('commander') const chalk = require('chalk') const _ = require('lodash') -const build = require('../dist/build').default +const Builder = require('../dist/build').default const { PROJECT_CONFIG, BUILD_TYPES } = require('../dist/util/constants') const appPath = process.cwd() const projectConfPath = path.join(appPath, PROJECT_CONFIG) @@ -37,10 +37,11 @@ if (env) { process.env.NODE_ENV = 'production' } } +const builder = new Builder(appPath) if (ui) { console.log(chalk.green(`开始编译 UI 库`)) - build(appPath, { + builder.build({ type: 'ui', watch, uiIndex @@ -52,7 +53,7 @@ if (plugin) { if (typeof plugin === 'boolean') { plugin = BUILD_TYPES.WEAPP } - build(appPath, { + builder.build({ type: BUILD_TYPES.PLUGIN, platform: plugin, watch @@ -76,7 +77,7 @@ if (typeof page === 'string') { console.log(chalk.green(`开始编译项目 ${chalk.bold(projectConf.projectName)}`)) } -build(appPath, { +builder.build({ type, watch, port: typeof port === 'string' ? port: undefined, diff --git a/packages/taro-cli/src/build.ts b/packages/taro-cli/src/build.ts index a4b0bd36f0b0..96c57724b790 100644 --- a/packages/taro-cli/src/build.ts +++ b/packages/taro-cli/src/build.ts @@ -1,131 +1,121 @@ import * as path from 'path' import * as fs from 'fs-extra' -import chalk from 'chalk' +import { SyncHook, Hook } from 'tapable' import * as _ from 'lodash' +import chalk from 'chalk' -import * as Util from './util' -import CONFIG from './config' import { BUILD_TYPES, PROJECT_CONFIG } from './util/constants' -import { IBuildConfig } from './util/types' +import { IBuildOptions, IProjectConfig, ICommonPlugin } from './util/types' +import { emptyDirectory } from './util' +import CONFIG from './config' -export default async function build (appPath, buildConfig: IBuildConfig) { - const { type, watch, platform, port, release, page, component, uiIndex } = buildConfig - const configDir = require(path.join(appPath, PROJECT_CONFIG))(_.merge) - const outputPath = path.join(appPath, configDir.outputRoot || CONFIG.OUTPUT_DIR) - if (!fs.existsSync(outputPath)) { - fs.ensureDirSync(outputPath) - } else if (type !== BUILD_TYPES.H5 && (type !== BUILD_TYPES.QUICKAPP || !watch)) { - Util.emptyDirectory(outputPath) - } - switch (type) { - case BUILD_TYPES.H5: - buildForH5(appPath, { watch, port }) - break - case BUILD_TYPES.WEAPP: - buildForWeapp(appPath, { watch, page, component }) - break - case BUILD_TYPES.SWAN: - buildForSwan(appPath, { watch, page, component }) - break - case BUILD_TYPES.ALIPAY: - buildForAlipay(appPath, { watch, page, component }) - break - case BUILD_TYPES.TT: - buildForTt(appPath, { watch, page, component }) - break - case BUILD_TYPES.RN: - buildForRN(appPath, { watch }) - break - case BUILD_TYPES.QUICKAPP: - buildForQuickApp(appPath, { watch, port, release }) - break - case BUILD_TYPES.QQ: - buildForQQ(appPath, { watch, page, component }) - break - case BUILD_TYPES.JD: - buildForJD(appPath, { watch }) - break - case BUILD_TYPES.UI: - buildForUILibrary(appPath, { watch, uiIndex }) - break - case BUILD_TYPES.PLUGIN: - buildForPlugin(appPath, { - watch, - platform - }) - break - default: - console.log(chalk.red('输入类型错误,目前只支持 weapp/swan/alipay/tt/h5/quickapp/rn 七端类型')) - } +interface IBuilderHooks { + beforeBuild: Hook, + afterBuild: Hook } -function buildForWeapp (appPath: string, buildConfig: IBuildConfig) { - require('./mini').build(appPath, Object.assign({ - adapter: BUILD_TYPES.WEAPP - }, buildConfig)) -} +export default class Builder { + hooks: IBuilderHooks + appPath: string + config: IProjectConfig + constructor (appPath: string) { + this.hooks = { + beforeBuild: new SyncHook(['config']), + afterBuild: new SyncHook(['builder']) + } -function buildForSwan (appPath: string, buildConfig: IBuildConfig) { - require('./mini').build(appPath, Object.assign({ - adapter: BUILD_TYPES.SWAN - }, buildConfig)) -} + this.appPath = appPath + this.init() + } -function buildForAlipay (appPath: string, buildConfig: IBuildConfig) { - require('./mini').build(appPath, Object.assign({ - adapter: BUILD_TYPES.ALIPAY - }, buildConfig)) -} + init () { + this.resolveConfig() + this.applyPlugins() + } -function buildForTt (appPath: string, buildConfig: IBuildConfig) { - require('./mini').build(appPath, Object.assign({ - adapter: BUILD_TYPES.TT - }, buildConfig)) -} + resolveConfig () { + this.config = require(path.join(this.appPath, PROJECT_CONFIG))(_.merge) + } -function buildForH5 (appPath: string, buildConfig: IBuildConfig) { - require('./h5').build(appPath, buildConfig) -} + applyPlugins () { + const commonConfig = Object.assign({}, { plugins: [] }, this.config.common) + const plugins = commonConfig.plugins + if (plugins.length) { + plugins.forEach((plugin: ICommonPlugin) => { + plugin.apply(this) + }) + } + } -function buildForRN (appPath: string, { watch }: IBuildConfig) { - require('./rn').build(appPath, { watch }) -} + emptyFirst ({ watch, type }) { + const outputPath = path.join(this.appPath, `${this.config.outputRoot || CONFIG.OUTPUT_DIR}}`) + if (!fs.existsSync(outputPath)) { + fs.ensureDirSync(outputPath) + } else if (type !== BUILD_TYPES.H5 && (type !== BUILD_TYPES.QUICKAPP || !watch)) { + emptyDirectory(outputPath) + } + } -function buildForQuickApp (appPath: string, { watch, port, release }: IBuildConfig) { - require('./mini').build(appPath, { - watch, - adapter: BUILD_TYPES.QUICKAPP, - port, - release - }) -} + build (buildOptions: IBuildOptions) { + this.hooks.beforeBuild.call(this.config) + const { type, watch, platform, port, uiIndex } = buildOptions + this.emptyFirst({ type, watch }) + switch (type) { + case BUILD_TYPES.H5: + this.buildForH5(this.appPath, { watch, port }) + break + case BUILD_TYPES.WEAPP: + case BUILD_TYPES.SWAN: + case BUILD_TYPES.ALIPAY: + case BUILD_TYPES.TT: + case BUILD_TYPES.QUICKAPP: + case BUILD_TYPES.QQ: + case BUILD_TYPES.JD: + this.buildForMini(this.appPath, buildOptions) + break + case BUILD_TYPES.RN: + this.buildForRN(this.appPath, { watch }) + break + case BUILD_TYPES.UI: + this.buildForUILibrary(this.appPath, { watch, uiIndex }) + break + case BUILD_TYPES.PLUGIN: + this.buildForPlugin(this.appPath, { + watch, + platform + }) + break + default: + console.log(chalk.red('输入类型错误,目前只支持 weapp/swan/alipay/tt/h5/quickapp/rn 七端类型')) + } + } -function buildForQQ (appPath: string, buildConfig: IBuildConfig) { - require('./mini').build(appPath, Object.assign({ - adapter: BUILD_TYPES.QQ - }, buildConfig)) -} + buildForH5 (appPath: string, buildOptions: IBuildOptions) { + require('./h5').build(appPath, buildOptions) + } -function buildForJD (appPath: string, { watch }: IBuildConfig) { - require('./mini').build(appPath, { - watch, - adapter: BUILD_TYPES.JD - }) -} + buildForMini (appPath: string, buildOptions: IBuildOptions) { + require('./mini/webpack').build(appPath, buildOptions, this) + } -function buildForUILibrary (appPath: string, { watch, uiIndex }: IBuildConfig) { - require('./ui/index').build(appPath, { watch, uiIndex }) -} + buildForRN (appPath: string, { watch }) { + require('./rn').build(appPath, { watch }) + } -function buildForPlugin (appPath: string, { watch, platform }) { - const typeMap = { - [BUILD_TYPES.WEAPP]: '微信', - [BUILD_TYPES.ALIPAY]: '支付宝' + buildForUILibrary (appPath: string, { watch, uiIndex }) { + require('./ui/index').build(appPath, { watch, uiIndex }) } - if (platform !== BUILD_TYPES.WEAPP && platform !== BUILD_TYPES.ALIPAY) { - console.log(chalk.red('目前插件编译仅支持 微信/支付宝 小程序!')) - return + + buildForPlugin (appPath: string, { watch, platform }) { + const typeMap = { + [BUILD_TYPES.WEAPP]: '微信', + [BUILD_TYPES.ALIPAY]: '支付宝' + } + if (platform !== BUILD_TYPES.WEAPP && platform !== BUILD_TYPES.ALIPAY) { + console.log(chalk.red('目前插件编译仅支持 微信/支付宝 小程序!')) + return + } + console.log(chalk.green(`开始编译${typeMap[platform]}小程序插件`)) + require('./plugin').build(appPath, { watch, platform }) } - console.log(chalk.green(`开始编译${typeMap[platform]}小程序插件`)) - require('./plugin').build(appPath, { watch, platform }) } diff --git a/packages/taro-cli/src/index.ts b/packages/taro-cli/src/index.ts index 3073694620dc..b99811b576ec 100644 --- a/packages/taro-cli/src/index.ts +++ b/packages/taro-cli/src/index.ts @@ -1,12 +1,12 @@ import Convertor from './convertor' -import build from './build' +import Builder from './build' import doctor from './doctor' import Project from './create/project' import { Compiler as H5Compiler } from './h5/index' export default { Convertor, - build, + Builder, doctor, Project, H5Compiler @@ -14,7 +14,7 @@ export default { export { Convertor, - build, + Builder, doctor, Project, H5Compiler diff --git a/packages/taro-cli/src/mini/webpack.ts b/packages/taro-cli/src/mini/webpack.ts index 35039c096136..c880b35b0814 100644 --- a/packages/taro-cli/src/mini/webpack.ts +++ b/packages/taro-cli/src/mini/webpack.ts @@ -5,6 +5,7 @@ import { IMiniAppBuildConfig } from '../util/types' import { BUILD_TYPES } from '../util/constants' import * as npmProcess from '../util/npm' import { getBabelConfig } from '../util' +import Builder from '../build' import { setBuildData, @@ -12,9 +13,8 @@ import { getBuildData } from './helper' -export async function build (appPath: string, { watch, adapter = BUILD_TYPES.WEAPP, envHasBeenSet = false, port, release }: IMiniAppBuildConfig) { +export async function build (appPath: string, { watch, adapter = BUILD_TYPES.WEAPP, envHasBeenSet = false, port, release }: IMiniAppBuildConfig, builder: Builder) { const buildData = setBuildData(appPath, adapter) - const isQuickApp = adapter === BUILD_TYPES.QUICKAPP process.env.TARO_ENV = adapter if (!envHasBeenSet) { setIsProduction(process.env.NODE_ENV === 'production' || !watch) @@ -23,11 +23,10 @@ export async function build (appPath: string, { watch, adapter = BUILD_TYPES.WEA await buildWithWebpack({ appPath - }) - + }, builder) } -async function buildWithWebpack ({ appPath }: { appPath: string }) { +async function buildWithWebpack ({ appPath }: { appPath: string }, builder) { const { entryFilePath, outputDir, @@ -54,5 +53,5 @@ async function buildWithWebpack ({ appPath }: { appPath: string }) { designWidth: projectConfig.designWidth, deviceRatio: projectConfig.deviceRatio } - miniRunner(miniRunnerOpts) + miniRunner(miniRunnerOpts, builder) } diff --git a/packages/taro-cli/src/util/types.ts b/packages/taro-cli/src/util/types.ts index 2150a62092f0..de721caad5d8 100644 --- a/packages/taro-cli/src/util/types.ts +++ b/packages/taro-cli/src/util/types.ts @@ -44,7 +44,7 @@ export interface IPrettierConfig { endOfLine?: 'auto' | 'lf' | 'crlf' | 'cr' } -export interface IBuildConfig { +export interface IBuildOptions { type?: BUILD_TYPES, watch?: boolean, platform?: string, @@ -341,6 +341,9 @@ export interface IManifestConfig extends ITaroManifestConfig { export interface IDeviceRatio { [key: string]: number } +export interface ICommonPlugin { + apply: (obj: object) => any +} export interface IProjectConfig { projectName?: string, @@ -355,6 +358,12 @@ export interface IProjectConfig { csso?: TogglableOptions, uglify?: TogglableOptions }, + common?: { + plugins?: ICommonPlugin[], + babel?: IBabelOptions, + csso?: TogglableOptions, + uglify?: TogglableOptions + }, ui?: { extraWatchFiles?: any[] },