UNPKG

3.5 kBPlain TextView Raw
1import * as path from 'path'
2import * as fs from 'fs-extra'
3import { SyncHook, Hook } from 'tapable'
4import * as _ from 'lodash'
5import chalk from 'chalk'
6import { IProjectConfig, ICommonPlugin } from '@tarojs/taro/types/compile'
7
8import { BUILD_TYPES, PROJECT_CONFIG } from './util/constants'
9import { IBuildOptions } from './util/types'
10import { emptyDirectory } from './util'
11import CONFIG from './config'
12
13interface IBuilderHooks {
14 beforeBuild: Hook,
15 afterBuild: Hook
16}
17
18export default class Builder {
19 hooks: IBuilderHooks
20 appPath: string
21 config: IProjectConfig
22
23 constructor (appPath: string) {
24 this.hooks = {
25 beforeBuild: new SyncHook(['config']),
26 afterBuild: new SyncHook(['builder'])
27 }
28
29 this.appPath = appPath
30 this.init()
31 }
32
33 init () {
34 this.resolveConfig()
35 this.applyPlugins()
36 }
37
38 resolveConfig () {
39 this.config = require(path.join(this.appPath, PROJECT_CONFIG))(_.merge)
40 }
41
42 applyPlugins () {
43 const plugins = this.config.plugins || []
44 if (plugins.length) {
45 plugins.forEach((plugin: ICommonPlugin) => {
46 plugin.apply(this)
47 })
48 }
49 }
50
51 emptyFirst ({watch, type}) {
52 const outputPath = path.join(this.appPath, `${this.config.outputRoot || CONFIG.OUTPUT_DIR}`)
53 if (!fs.existsSync(outputPath)) {
54 fs.ensureDirSync(outputPath)
55 } else if (type !== BUILD_TYPES.H5 && (type !== BUILD_TYPES.QUICKAPP || !watch)) {
56 emptyDirectory(outputPath)
57 }
58 }
59
60 build (buildOptions: IBuildOptions) {
61 this.hooks.beforeBuild.call(this.config)
62 const {type, watch, platform, port, uiIndex} = buildOptions
63 this.emptyFirst({type, watch})
64 switch (type) {
65 case BUILD_TYPES.H5:
66 this.buildForH5(this.appPath, {watch, port})
67 break
68 case BUILD_TYPES.WEAPP:
69 case BUILD_TYPES.SWAN:
70 case BUILD_TYPES.ALIPAY:
71 case BUILD_TYPES.TT:
72 case BUILD_TYPES.QUICKAPP:
73 case BUILD_TYPES.QQ:
74 case BUILD_TYPES.JD:
75 this.buildForMini(this.appPath, buildOptions)
76 break
77 case BUILD_TYPES.RN:
78 this.buildForRN(this.appPath, {watch, port})
79 break
80 case BUILD_TYPES.UI:
81 this.buildForUILibrary(this.appPath, {watch, uiIndex})
82 break
83 case BUILD_TYPES.PLUGIN:
84 this.buildForPlugin(this.appPath, {
85 watch,
86 platform
87 })
88 break
89 default:
90 console.log(
91 chalk.red('输入类型错误,目前只支持 weapp/swan/alipay/tt/qq/h5/quickapp/rn 八端类型'))
92 }
93 }
94
95 buildForH5 (appPath: string, buildOptions: IBuildOptions) {
96 require('./h5').build(appPath, buildOptions)
97 }
98
99 buildForMini (appPath: string, buildOptions: IBuildOptions) {
100 require('./mini').build(appPath, buildOptions, null, this)
101 }
102
103 buildForRN (appPath: string, {watch, port}) {
104 require('./rn').build(appPath, {watch, port})
105 }
106
107 buildForUILibrary (appPath: string, {watch, uiIndex}) {
108 require('./ui/index').build(appPath, {watch, uiIndex})
109 }
110
111 buildForPlugin (appPath: string, {watch, platform}) {
112 const typeMap = {
113 [BUILD_TYPES.WEAPP]: '微信',
114 [BUILD_TYPES.ALIPAY]: '支付宝'
115 }
116 if (platform !== BUILD_TYPES.WEAPP && platform !== BUILD_TYPES.ALIPAY) {
117 console.log(chalk.red('目前插件编译仅支持 微信/支付宝 小程序!'))
118 return
119 }
120 console.log(chalk.green(`开始编译${typeMap[platform]}小程序插件`))
121 require('./plugin').build(appPath, {watch, platform}, this)
122 }
123}