@@ -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,73 @@ 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
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-
171155 const fileInfo = resolveTarget ( resourcePath , options . entry )
172156 cacheFileInfo ( resourcePath , fileInfo )
173157 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+ }
174199
175200 if ( isApp || isPage ) {
176201 // 生成入口 json
@@ -213,4 +238,32 @@ function compileMP (content, mpOptioins) {
213238 return content
214239}
215240
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+
216269module . exports = { compileWxml, compileMPScript, compileMP }
0 commit comments