@@ -4,8 +4,9 @@ const compiler = require('mpvue-template-compiler')
4
4
const babel = require ( 'babel-core' )
5
5
const path = require ( 'path' )
6
6
const fs = require ( 'fs' )
7
+ const deepEqual = require ( 'deep-equal' )
7
8
8
- const { parseConfig, parseComponentsDeps } = require ( './parse' )
9
+ const { parseConfig, parseComponentsDeps, parseGlobalComponents , clearGlobalComponents } = require ( './parse' )
9
10
const { parseComponentsDeps : parseComponentsDepsTs } = require ( './parse-ts' )
10
11
const { genScript, genStyle, genPageWxml } = require ( './templates' )
11
12
@@ -62,7 +63,11 @@ function genComponentWxml (compiled, options, emitFile, emitError, emitWarning)
62
63
return htmlBeautify ( wxmlCodeStr )
63
64
}
64
65
66
+ // 更新全局组件时,需要重新生成wxml,用这个字段保存所有需要更新的页面及其参数
67
+ const cacheCreateWxmlFns = { }
68
+
65
69
function createWxml ( emitWarning , emitError , emitFile , resourcePath , rootComponent , compiled , html ) {
70
+ cacheCreateWxmlFns [ resourcePath ] = arguments
66
71
const { pageType, moduleId, components, src } = getFileInfo ( resourcePath ) || { }
67
72
68
73
// 这儿一个黑魔法,和 webpack 约定的规范写法有点偏差!
@@ -124,53 +129,73 @@ function compileMPScript (script, mpOptioins, moduleId) {
124
129
125
130
// 处理子组件的信息
126
131
const components = { }
132
+ const fileInfo = resolveTarget ( this . resourcePath , this . options . entry )
127
133
if ( originComponents ) {
128
- const allP = Object . keys ( originComponents ) . map ( k => {
129
- return new Promise ( ( resolve , reject ) => {
130
- this . resolve ( this . context , originComponents [ k ] , ( err , realSrc ) => {
131
- if ( err ) return reject ( err )
132
- const com = covertCCVar ( k )
133
- const comName = getCompNameBySrc ( realSrc )
134
- components [ com ] = { src : comName , name : comName }
135
- resolve ( )
136
- } )
137
- } )
134
+ resolveSrc ( originComponents , components , this . resolve , this . context ) . then ( ( ) => {
135
+ resolveComponent ( this . resourcePath , fileInfo , importsMap , components , moduleId )
136
+ } ) . catch ( err => {
137
+ console . error ( err )
138
+ resolveComponent ( this . resourcePath , fileInfo , importsMap , components , moduleId )
138
139
} )
139
- Promise . all ( allP )
140
- . then ( res => {
141
- components . isCompleted = true
142
- } )
143
- . catch ( err => {
144
- console . error ( err )
145
- components . isCompleted = true
146
- } )
147
140
} else {
148
- components . isCompleted = true
141
+ resolveComponent ( this . resourcePath , fileInfo , importsMap , components , moduleId )
149
142
}
150
143
151
- const fileInfo = resolveTarget ( this . resourcePath , this . options . entry )
152
- cacheFileInfo ( this . resourcePath , fileInfo , { importsMap, components, moduleId } )
153
-
154
144
return script
155
145
}
156
146
157
147
// checkMPEntry 针对 entry main.js 的入口处理
158
148
// 编译出 app, page 的入口js/wxml/json
159
149
160
150
const startPageReg = / ^ \^ /
161
-
151
+ let globalComponents
162
152
function compileMP ( content , mpOptioins ) {
163
153
const { resourcePath, emitError, emitFile, emitWarning, resolve, context, options } = this
164
154
165
- const babelrc = getBabelrc ( mpOptioins . globalBabelrc )
166
- const { metadata } = babel . transform ( content , { extends : babelrc , plugins : [ parseConfig ] } )
167
-
168
- // metadata: config
169
- const { config, rootComponent } = metadata
170
-
171
155
const fileInfo = resolveTarget ( resourcePath , options . entry )
172
156
cacheFileInfo ( resourcePath , fileInfo )
173
157
const { src, name, isApp, isPage } = fileInfo
158
+ if ( isApp ) {
159
+ // 解析前将可能存在的全局组件清空
160
+ clearGlobalComponents ( )
161
+ }
162
+
163
+ const babelrc = getBabelrc ( mpOptioins . globalBabelrc )
164
+ // app入口进行全局component解析
165
+ const { metadata } = babel . transform ( content , { extends : babelrc , plugins : isApp ? [ parseConfig , parseGlobalComponents ] : [ parseConfig ] } )
166
+
167
+ // metadata: config
168
+ const { config, rootComponent, globalComponents : globalComps } = metadata
169
+
170
+ if ( isApp ) {
171
+ // 保存旧数据,用于对比
172
+ const oldGlobalComponents = globalComponents
173
+ // 开始解析组件路径时把全局组件清空,解析完成后再进行赋值,标志全局组件解析完成
174
+ globalComponents = null
175
+
176
+ // 解析全局组件的路径
177
+ const components = { }
178
+ resolveSrc ( globalComps , components , resolve , context ) . then ( ( ) => {
179
+ handleResult ( components )
180
+ } ) . catch ( err => {
181
+ console . error ( err )
182
+ handleResult ( components )
183
+ } )
184
+ const handleResult = components => {
185
+ globalComponents = components
186
+ // 热更时,如果全局组件更新,需要重新生成所有的wxml
187
+ if ( oldGlobalComponents && ! deepEqual ( oldGlobalComponents , globalComponents ) ) {
188
+ // 更新所有页面的组件
189
+ Object . keys ( cacheResolveComponents ) . forEach ( k => {
190
+ resolveComponent ( ...cacheResolveComponents [ k ] )
191
+ } )
192
+ // 重新生成所有wxml
193
+ Object . keys ( cacheCreateWxmlFns ) . forEach ( k => {
194
+ createWxml ( ...cacheCreateWxmlFns [ k ] )
195
+ } )
196
+ }
197
+ }
198
+ }
174
199
175
200
if ( isApp || isPage ) {
176
201
// 生成入口 json
@@ -213,4 +238,32 @@ function compileMP (content, mpOptioins) {
213
238
return content
214
239
}
215
240
241
+ function resolveSrc ( originComponents , components , resolveFn , context ) {
242
+ return Promise . all ( Object . keys ( originComponents ) . map ( k => {
243
+ return new Promise ( ( resolve , reject ) => {
244
+ resolveFn ( context , originComponents [ k ] , ( err , realSrc ) => {
245
+ if ( err ) return reject ( err )
246
+ const com = covertCCVar ( k )
247
+ const comName = getCompNameBySrc ( realSrc )
248
+ components [ com ] = { src : comName , name : comName }
249
+ resolve ( )
250
+ } )
251
+ } )
252
+ } ) )
253
+ }
254
+
255
+ const cacheResolveComponents = { }
256
+ function resolveComponent ( resourcePath , fileInfo , importsMap , localComponents , moduleId ) {
257
+ // 需要等待全局组件解析完成
258
+ if ( ! globalComponents ) {
259
+ setTimeout ( resolveComponent , 20 , ...arguments )
260
+ } else {
261
+ // 保存当前所有参数,在热更时如果全局组件发生变化,需要进行组件更新
262
+ cacheResolveComponents [ resourcePath ] = arguments
263
+ const components = Object . assign ( { } , globalComponents , localComponents )
264
+ components . isCompleted = true
265
+ cacheFileInfo ( resourcePath , fileInfo , { importsMap, components, moduleId } )
266
+ }
267
+ }
268
+
216
269
module . exports = { compileWxml, compileMPScript, compileMP }
0 commit comments