@@ -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,71 @@ 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
155
+ const fileInfo = resolveTarget ( resourcePath , options . entry )
156
+ cacheFileInfo ( resourcePath , fileInfo )
157
+ const { src, name, isApp, isPage } = fileInfo
158
+
165
159
const babelrc = getBabelrc ( mpOptioins . globalBabelrc )
166
- const { metadata } = babel . transform ( content , { extends : babelrc , plugins : [ parseConfig ] } )
160
+ // app入口进行全局component解析
161
+ const { metadata } = babel . transform ( content , { extends : babelrc , plugins : isApp ? [ parseConfig , parseGlobalComponents ] : [ parseConfig ] } )
167
162
168
163
// metadata: config
169
- const { config, rootComponent } = metadata
164
+ const { config, rootComponent, globalComponents : globalComps } = metadata
165
+
166
+ if ( isApp ) {
167
+ // 保存旧数据,用于对比
168
+ const oldGlobalComponents = globalComponents
169
+ // 开始解析app入口文件时把全局组件清空,解析完成后再进行赋值,标志全局组件解析完成
170
+ globalComponents = null
171
+ clearGlobalComponents ( )
172
+
173
+ const handleResult = ( ) => {
174
+ globalComponents = components
175
+ // 热更时,如果全局组件更新,需要重新生成所有的wxml
176
+ if ( oldGlobalComponents && ! deepEqual ( oldGlobalComponents , globalComponents ) ) {
177
+ // 更新所有页面的组件
178
+ Object . keys ( cacheResolveComponents ) . forEach ( k => {
179
+ resolveComponent ( ...cacheResolveComponents [ k ] )
180
+ } )
181
+ // 重新生成所有wxml
182
+ Object . keys ( cacheCreateWxmlFns ) . forEach ( k => {
183
+ createWxml ( ...cacheCreateWxmlFns [ k ] )
184
+ } )
185
+ }
186
+ }
170
187
171
- const fileInfo = resolveTarget ( resourcePath , options . entry )
172
- cacheFileInfo ( resourcePath , fileInfo )
173
- const { src, name, isApp, isPage } = fileInfo
188
+ // 解析全局组件的路径
189
+ const components = { }
190
+ resolveSrc ( globalComps , components , resolve , context ) . then ( ( ) => {
191
+ handleResult ( )
192
+ } ) . catch ( err => {
193
+ console . error ( err )
194
+ handleResult ( )
195
+ } )
196
+ }
174
197
175
198
if ( isApp || isPage ) {
176
199
// 生成入口 json
@@ -213,4 +236,32 @@ function compileMP (content, mpOptioins) {
213
236
return content
214
237
}
215
238
239
+ function resolveSrc ( originComponents , components , resolveFn , context ) {
240
+ return Promise . all ( Object . keys ( originComponents ) . map ( k => {
241
+ return new Promise ( ( resolve , reject ) => {
242
+ resolveFn ( context , originComponents [ k ] , ( err , realSrc ) => {
243
+ if ( err ) return reject ( err )
244
+ const com = covertCCVar ( k )
245
+ const comName = getCompNameBySrc ( realSrc )
246
+ components [ com ] = { src : comName , name : comName }
247
+ resolve ( )
248
+ } )
249
+ } )
250
+ } ) )
251
+ }
252
+
253
+ const cacheResolveComponents = { }
254
+ function resolveComponent ( resourcePath , fileInfo , importsMap , localComponents , moduleId ) {
255
+ // 需要等待全局组件解析完成
256
+ if ( ! globalComponents ) {
257
+ setTimeout ( resolveComponent , 20 , ...arguments )
258
+ } else {
259
+ // 保存当前所有参数,在热更时如果全局组件发生变化,需要进行组件更新
260
+ cacheResolveComponents [ resourcePath ] = arguments
261
+ const components = Object . assign ( { } , globalComponents , localComponents )
262
+ components . isCompleted = true
263
+ cacheFileInfo ( resourcePath , fileInfo , { importsMap, components, moduleId } )
264
+ }
265
+ }
266
+
216
267
module . exports = { compileWxml, compileMPScript, compileMP }
0 commit comments