@@ -4,8 +4,9 @@ const compiler = require('mpvue-template-compiler')
44const babel = require ( 'babel-core' )
55const path = require ( 'path' )
66const fs = require ( 'fs' )
7+ const deepEqual = require ( 'deep-equal' )
78
8- const { parseConfig, parseComponentsDeps } = require ( './parse' )
9+ const { parseConfig, parseComponentsDeps, parseGlobalComponents , clearGlobalComponents } = require ( './parse' )
910const { parseComponentsDeps : parseComponentsDepsTs } = require ( './parse-ts' )
1011const { genScript, genStyle, genPageWxml } = require ( './templates' )
1112
@@ -62,7 +63,11 @@ function genComponentWxml (compiled, options, emitFile, emitError, emitWarning)
6263 return htmlBeautify ( wxmlCodeStr )
6364}
6465
66+ // 更新全局组件时,需要重新生成wxml,用这个字段保存所有需要更新的页面及其参数
67+ const cacheCreateWxmlFns = { }
68+
6569function createWxml ( emitWarning , emitError , emitFile , resourcePath , rootComponent , compiled , html ) {
70+ cacheCreateWxmlFns [ resourcePath ] = arguments
6671 const { pageType, moduleId, components, src } = getFileInfo ( resourcePath ) || { }
6772
6873 // 这儿一个黑魔法,和 webpack 约定的规范写法有点偏差!
@@ -124,53 +129,71 @@ function compileMPScript (script, mpOptioins, moduleId) {
124129
125130 // 处理子组件的信息
126131 const components = { }
132+ const fileInfo = resolveTarget ( this . resourcePath , this . options . entry )
127133 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 )
138139 } )
139- Promise . all ( allP )
140- . then ( res => {
141- components . isCompleted = true
142- } )
143- . catch ( err => {
144- console . error ( err )
145- components . isCompleted = true
146- } )
147140 } else {
148- components . isCompleted = true
141+ resolveComponent ( this . resourcePath , fileInfo , importsMap , components , moduleId )
149142 }
150143
151- const fileInfo = resolveTarget ( this . resourcePath , this . options . entry )
152- cacheFileInfo ( this . resourcePath , fileInfo , { importsMap, components, moduleId } )
153-
154144 return script
155145}
156146
157147// checkMPEntry 针对 entry main.js 的入口处理
158148// 编译出 app, page 的入口js/wxml/json
159149
160150const startPageReg = / ^ \^ /
161-
151+ let globalComponents
162152function compileMP ( content , mpOptioins ) {
163153 const { resourcePath, emitError, emitFile, emitWarning, resolve, context, options } = this
164154
155+ const fileInfo = resolveTarget ( resourcePath , options . entry )
156+ cacheFileInfo ( resourcePath , fileInfo )
157+ const { src, name, isApp, isPage } = fileInfo
158+
165159 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 ] } )
167162
168163 // 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+ }
170187
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+ }
174197
175198 if ( isApp || isPage ) {
176199 // 生成入口 json
@@ -213,4 +236,32 @@ function compileMP (content, mpOptioins) {
213236 return content
214237}
215238
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+
216267module . exports = { compileWxml, compileMPScript, compileMP }
0 commit comments