@mpxjs/webpack-plugin 2.8.40-test → 2.8.40-test.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/lib/dependencies/DynamicEntryDependency.js +10 -16
  2. package/lib/index.js +87 -60
  3. package/lib/json-compiler/helper.js +8 -5
  4. package/lib/json-compiler/index.js +2 -2
  5. package/lib/loader.js +28 -27
  6. package/lib/parser.js +0 -1
  7. package/lib/platform/index.js +15 -4
  8. package/lib/platform/json/wx/index.js +3 -5
  9. package/lib/platform/run-rules.js +1 -2
  10. package/lib/platform/template/normalize-component-rules.js +41 -42
  11. package/lib/platform/template/wx/component-config/component.js +1 -2
  12. package/lib/platform/template/wx/component-config/fix-component-name.js +21 -0
  13. package/lib/platform/template/wx/component-config/index.js +4 -4
  14. package/lib/platform/template/wx/index.js +21 -16
  15. package/lib/runtime/base.styl +9 -1
  16. package/lib/runtime/components/web/getInnerListeners.js +1 -2
  17. package/lib/runtime/components/web/mpx-image.vue +13 -10
  18. package/lib/runtime/components/web/mpx-movable-view.vue +1 -1
  19. package/lib/runtime/components/web/mpx-picker-view-column.vue +10 -2
  20. package/lib/runtime/components/web/mpx-picker.vue +9 -1
  21. package/lib/runtime/components/web/mpx-swiper.vue +2 -2
  22. package/lib/runtime/optionProcessor.js +321 -264
  23. package/lib/runtime/stringify.wxs +44 -8
  24. package/lib/style-compiler/index.js +1 -2
  25. package/lib/template-compiler/compiler.js +74 -56
  26. package/lib/utils/check-core-version-match.js +18 -14
  27. package/lib/web/processJSON.js +4 -3
  28. package/lib/web/processMainScript.js +84 -0
  29. package/lib/web/processScript.js +21 -204
  30. package/lib/web/processTemplate.js +4 -1
  31. package/lib/web/script-helper.js +202 -0
  32. package/package.json +5 -4
  33. package/lib/platform/template/wx/component-config/fix-html-tag.js +0 -17
  34. package/lib/style-compiler/plugins/trim.js +0 -15
@@ -1,313 +1,370 @@
1
- import { isBrowser } from './env'
2
1
  import { hasOwn } from './utils'
2
+ import { isBrowser } from './env'
3
3
  import transRpxStyle from './transRpxStyle'
4
4
  import animation from './animation'
5
5
 
6
- export default function processOption (
7
- option,
8
- ctorType,
9
- firstPage,
10
- outputPath,
11
- pageConfig,
12
- pagesMap,
13
- componentsMap,
14
- tabBarMap,
15
- componentGenerics,
16
- genericsInfo,
17
- mixin,
18
- hasApp,
19
- Vue,
20
- VueRouter
6
+ export default function processComponentOption (
7
+ {
8
+ option,
9
+ ctorType,
10
+ outputPath,
11
+ pageConfig,
12
+ componentsMap,
13
+ componentGenerics,
14
+ genericsInfo,
15
+ mixin,
16
+ hasApp
17
+ }
21
18
  ) {
22
- if (ctorType === 'app') {
23
- // 对于app中的组件需要全局注册
24
- for (const componentName in componentsMap) {
25
- if (hasOwn(componentsMap, componentName)) {
26
- const component = componentsMap[componentName]
27
- Vue.component(componentName, component)
19
+ // 局部注册页面和组件中依赖的组件
20
+ for (const componentName in componentsMap) {
21
+ if (hasOwn(componentsMap, componentName)) {
22
+ const component = componentsMap[componentName]
23
+ if (!option.components) {
24
+ option.components = {}
28
25
  }
26
+ option.components[componentName] = component
29
27
  }
28
+ }
30
29
 
31
- Vue.directive('animation', animation)
30
+ if (genericsInfo) {
31
+ const genericHash = genericsInfo.hash
32
+ global.__mpxGenericsMap[genericHash] = {}
33
+ Object.keys(genericsInfo.map).forEach((genericValue) => {
34
+ if (componentsMap[genericValue]) {
35
+ global.__mpxGenericsMap[genericHash][genericValue] = componentsMap[genericValue]
36
+ } else {
37
+ console.warn(`[Mpx runtime warn]: generic value "${genericValue}" must be
38
+ registered in parent context!`)
39
+ }
40
+ })
41
+ }
32
42
 
33
- Vue.filter('transRpxStyle', transRpxStyle)
43
+ if (componentGenerics) {
44
+ option.props = option.props || {}
45
+ option.props.generichash = String
46
+ Object.keys(componentGenerics).forEach((genericName) => {
47
+ if (componentGenerics[genericName].default) {
48
+ option.props[`generic${genericName}`] = {
49
+ type: String,
50
+ default: `${genericName}default`
51
+ }
52
+ } else {
53
+ option.props[`generic${genericName}`] = String
54
+ }
55
+ })
56
+ }
34
57
 
35
- const routes = []
58
+ if (ctorType === 'page') {
59
+ option.__mpxPageConfig = Object.assign({}, global.__mpxPageConfig, pageConfig)
60
+ }
36
61
 
37
- for (const pagePath in pagesMap) {
38
- if (hasOwn(pagesMap, pagePath)) {
39
- const page = pagesMap[pagePath]
40
- routes.push({
41
- path: '/' + pagePath,
42
- component: page
43
- })
44
- }
62
+ if (!hasApp) {
63
+ option.directives = { animation }
64
+ option.filters = { transRpxStyle }
65
+ }
66
+
67
+ if (option.mixins) {
68
+ option.mixins.push(mixin)
69
+ } else {
70
+ option.mixins = [mixin]
71
+ }
72
+
73
+ if (outputPath) {
74
+ option.componentPath = '/' + outputPath
75
+ }
76
+
77
+ return option
78
+ }
79
+
80
+ export function getComponent (component, extendOptions) {
81
+ component = component.__esModule ? component.default : component
82
+ // eslint-disable-next-line
83
+ if (extendOptions) Object.assign(component, extendOptions)
84
+ return component
85
+ }
86
+
87
+ export function getWxsMixin (wxsModules) {
88
+ if (!wxsModules || !Object.keys(wxsModules).length) return {}
89
+ return {
90
+ created () {
91
+ Object.keys(wxsModules).forEach((key) => {
92
+ if (key in this) {
93
+ console.error(`[Mpx runtime error]: The wxs module key [${key}] exist in the component/page instance already, please check and rename it!`)
94
+ } else {
95
+ this[key] = wxsModules[key]
96
+ }
97
+ })
45
98
  }
99
+ }
100
+ }
46
101
 
47
- if (routes.length) {
48
- if (firstPage) {
49
- routes.push({
50
- path: '/',
51
- redirect: '/' + firstPage
52
- })
53
- }
54
- const webRouteConfig = global.__mpx.config.webRouteConfig
55
- global.__mpxRouter = option.router = new VueRouter({
56
- ...webRouteConfig,
57
- routes: routes
102
+ function createApp ({ componentsMap, Vue, pagesMap, firstPage, VueRouter, App, tabBarMap }) {
103
+ const option = {}
104
+ // 对于app中的组件需要全局注册
105
+ for (const componentName in componentsMap) {
106
+ if (hasOwn(componentsMap, componentName)) {
107
+ const component = componentsMap[componentName]
108
+ Vue.component(componentName, component)
109
+ }
110
+ }
111
+
112
+ Vue.directive('animation', animation)
113
+
114
+ Vue.filter('transRpxStyle', transRpxStyle)
115
+
116
+ Vue.config.ignoredElements = ['page']
117
+
118
+ const routes = []
119
+
120
+ for (const pagePath in pagesMap) {
121
+ if (hasOwn(pagesMap, pagePath)) {
122
+ const page = pagesMap[pagePath]
123
+ routes.push({
124
+ path: '/' + pagePath,
125
+ component: page
58
126
  })
59
- global.__mpxRouter.stack = []
60
- global.__mpxRouter.lastStack = null
61
- global.__mpxRouter.needCache = null
62
- global.__mpxRouter.needRemove = []
63
- global.__mpxRouter.eventChannelMap = {}
64
- // 处理reLaunch中传递的url并非首页时的replace逻辑
65
- global.__mpxRouter.beforeEach(function (to, from, next) {
66
- let action = global.__mpxRouter.__mpxAction
67
- const stack = global.__mpxRouter.stack
127
+ }
128
+ }
68
129
 
69
- // 处理人为操作
70
- if (!action) {
71
- if (stack.length > 1 && stack[stack.length - 2].path === to.path) {
72
- action = {
73
- type: 'back',
74
- delta: 1
75
- }
76
- } else {
77
- action = {
78
- type: 'to'
79
- }
130
+ if (routes.length) {
131
+ if (firstPage) {
132
+ routes.push({
133
+ path: '/',
134
+ redirect: '/' + firstPage
135
+ })
136
+ }
137
+ const webRouteConfig = global.__mpx.config.webRouteConfig
138
+ global.__mpxRouter = option.router = new VueRouter({
139
+ ...webRouteConfig,
140
+ routes: routes
141
+ })
142
+ global.__mpxRouter.stack = []
143
+ global.__mpxRouter.lastStack = null
144
+ global.__mpxRouter.needCache = null
145
+ global.__mpxRouter.needRemove = []
146
+ global.__mpxRouter.eventChannelMap = {}
147
+ // 处理reLaunch中传递的url并非首页时的replace逻辑
148
+ global.__mpxRouter.beforeEach(function (to, from, next) {
149
+ let action = global.__mpxRouter.__mpxAction
150
+ const stack = global.__mpxRouter.stack
151
+
152
+ // 处理人为操作
153
+ if (!action) {
154
+ if (stack.length > 1 && stack[stack.length - 2].path === to.path) {
155
+ action = {
156
+ type: 'back',
157
+ delta: 1
158
+ }
159
+ } else {
160
+ action = {
161
+ type: 'to'
80
162
  }
81
163
  }
164
+ }
82
165
 
83
- const pageInRoutes = routes.some(item => item.path === to.path)
84
- if (!pageInRoutes) {
85
- if (stack.length < 1) {
86
- if (global.__mpxRouter.app.$options.onPageNotFound) {
87
- // onPageNotFound,仅首次进入时生效
88
- global.__mpxRouter.app.$options.onPageNotFound({
89
- path: to.path,
90
- query: to.query,
91
- isEntryPage: true
92
- })
93
- return
94
- } else {
95
- console.warn(`[Mpx runtime warn]: the ${to.path} path does not exist in the application,will redirect to the home page path ${firstPage}`)
96
- return next({
97
- path: firstPage,
98
- replace: true
99
- })
100
- }
166
+ const pageInRoutes = routes.some(item => item.path === to.path)
167
+ if (!pageInRoutes) {
168
+ if (stack.length < 1) {
169
+ if (global.__mpxRouter.app.$options.onPageNotFound) {
170
+ // onPageNotFound,仅首次进入时生效
171
+ global.__mpxRouter.app.$options.onPageNotFound({
172
+ path: to.path,
173
+ query: to.query,
174
+ isEntryPage: true
175
+ })
176
+ return
101
177
  } else {
102
- const typeMethodMap = {
103
- to: 'navigateTo',
104
- redirect: 'redirectTo',
105
- back: 'navigateBack',
106
- switch: 'switchTab',
107
- reLaunch: 'reLaunch'
108
- }
109
- const method = typeMethodMap[action.type]
110
- throw new Error(`${method}:fail page "${to.path}" is not found`)
178
+ console.warn(`[Mpx runtime warn]: the ${to.path} path does not exist in the application,will redirect to the home page path ${firstPage}`)
179
+ return next({
180
+ path: firstPage,
181
+ replace: true
182
+ })
183
+ }
184
+ } else {
185
+ const typeMethodMap = {
186
+ to: 'navigateTo',
187
+ redirect: 'redirectTo',
188
+ back: 'navigateBack',
189
+ switch: 'switchTab',
190
+ reLaunch: 'reLaunch'
111
191
  }
192
+ const method = typeMethodMap[action.type]
193
+ throw new Error(`${method}:fail page "${to.path}" is not found`)
112
194
  }
195
+ }
113
196
 
114
- const insertItem = {
115
- path: to.path
116
- }
117
- // 构建历史栈
118
- switch (action.type) {
119
- case 'to':
120
- stack.push(insertItem)
121
- global.__mpxRouter.needCache = insertItem
122
- if (action.eventChannel) global.__mpxRouter.eventChannelMap[to.path.slice(1)] = action.eventChannel
123
- break
124
- case 'back':
125
- global.__mpxRouter.needRemove = stack.splice(stack.length - action.delta, action.delta)
126
- break
127
- case 'redirect':
128
- global.__mpxRouter.needRemove = stack.splice(stack.length - 1, 1, insertItem)
129
- global.__mpxRouter.needCache = insertItem
130
- break
131
- case 'switch':
132
- if (!action.replaced) {
133
- action.replaced = true
134
- return next({
135
- path: action.path,
136
- replace: true
137
- })
138
- } else {
139
- // 将非tabBar页面remove
140
- let tabItem = null
141
- global.__mpxRouter.needRemove = stack.filter((item) => {
142
- if (tabBarMap[item.path.slice(1)]) {
143
- tabItem = item
144
- tabItem.path = to.path
145
- return false
146
- }
147
- return true
148
- })
149
- if (tabItem) {
150
- global.__mpxRouter.stack = [tabItem]
151
- } else {
152
- global.__mpxRouter.stack = [insertItem]
153
- global.__mpxRouter.needCache = insertItem
197
+ const insertItem = {
198
+ path: to.path
199
+ }
200
+ // 构建历史栈
201
+ switch (action.type) {
202
+ case 'to':
203
+ stack.push(insertItem)
204
+ global.__mpxRouter.needCache = insertItem
205
+ if (action.eventChannel) global.__mpxRouter.eventChannelMap[to.path.slice(1)] = action.eventChannel
206
+ break
207
+ case 'back':
208
+ global.__mpxRouter.needRemove = stack.splice(stack.length - action.delta, action.delta)
209
+ break
210
+ case 'redirect':
211
+ global.__mpxRouter.needRemove = stack.splice(stack.length - 1, 1, insertItem)
212
+ global.__mpxRouter.needCache = insertItem
213
+ break
214
+ case 'switch':
215
+ if (!action.replaced) {
216
+ action.replaced = true
217
+ return next({
218
+ path: action.path,
219
+ replace: true
220
+ })
221
+ } else {
222
+ // 将非tabBar页面remove
223
+ let tabItem = null
224
+ global.__mpxRouter.needRemove = stack.filter((item) => {
225
+ if (tabBarMap[item.path.slice(1)] && !tabItem) {
226
+ tabItem = item
227
+ tabItem.path = to.path
228
+ return false
154
229
  }
155
- }
156
- break
157
- case 'reLaunch':
158
- if (!action.replaced) {
159
- action.replaced = true
160
- return next({
161
- path: action.path,
162
- query: {
163
- routeCount: action.routeCount
164
- },
165
- replace: true
166
- })
230
+ return true
231
+ })
232
+ if (tabItem) {
233
+ global.__mpxRouter.stack = [tabItem]
167
234
  } else {
168
- global.__mpxRouter.needRemove = stack
169
235
  global.__mpxRouter.stack = [insertItem]
170
236
  global.__mpxRouter.needCache = insertItem
171
237
  }
172
- }
173
- next()
174
- })
175
- // 处理visibilitychange时触发当前活跃页面组件的onshow/onhide
176
- if (isBrowser) {
177
- const errorHandler = function (args, fromVue) {
178
- if (global.__mpxAppCbs && global.__mpxAppCbs.error && global.__mpxAppCbs.error.length) {
179
- global.__mpxAppCbs.error.forEach((cb) => {
180
- cb.apply(null, args)
181
- })
182
- } else if (fromVue) {
183
- throw args[0]
184
238
  }
185
- }
186
- Vue.config.errorHandler = (...args) => {
187
- return errorHandler(args, true)
188
- }
189
- window.addEventListener('error', (event) => {
190
- return errorHandler([event.error, event])
191
- })
192
- window.addEventListener('unhandledrejection', (event) => {
193
- return errorHandler([event.reason, event])
194
- })
195
- document.addEventListener('visibilitychange', function () {
196
- const vnode = global.__mpxRouter && global.__mpxRouter.__mpxActiveVnode
197
- if (vnode && vnode.componentInstance) {
198
- const currentPage = vnode.tag.endsWith('mpx-tab-bar-container') ? vnode.componentInstance.$refs.tabBarPage : vnode.componentInstance
199
- if (document.hidden) {
200
- if (global.__mpxAppCbs && global.__mpxAppCbs.hide) {
201
- global.__mpxAppCbs.hide.forEach((cb) => {
202
- cb()
203
- })
204
- }
205
- if (currentPage) {
206
- currentPage.mpxPageStatus = 'hide'
207
- }
208
- } else {
209
- if (global.__mpxAppCbs && global.__mpxAppCbs.show) {
210
- global.__mpxAppCbs.show.forEach((cb) => {
211
- // todo 实现app.onShow参数
212
- /* eslint-disable node/no-callback-literal */
213
- cb({})
214
- })
215
- }
216
- if (currentPage) {
217
- currentPage.mpxPageStatus = 'show'
218
- }
219
- }
239
+ break
240
+ case 'reLaunch':
241
+ if (!action.replaced) {
242
+ action.replaced = true
243
+ return next({
244
+ path: action.path,
245
+ query: {
246
+ routeCount: action.routeCount
247
+ },
248
+ replace: true
249
+ })
250
+ } else {
251
+ global.__mpxRouter.needRemove = stack
252
+ global.__mpxRouter.stack = [insertItem]
253
+ global.__mpxRouter.needCache = insertItem
220
254
  }
221
- })
222
- // 初始化length
223
- global.__mpxRouter.__mpxHistoryLength = global.history.length
224
255
  }
225
- }
226
-
227
- // 注入pinia
228
- if (global.__mpxPinia) {
229
- option.pinia = global.__mpxPinia
230
- }
231
- } else {
232
- // 局部注册页面和组件中依赖的组件
233
- for (const componentName in componentsMap) {
234
- if (hasOwn(componentsMap, componentName)) {
235
- const component = componentsMap[componentName]
236
- if (!option.components) {
237
- option.components = {}
256
+ next()
257
+ })
258
+ // 处理visibilitychange时触发当前活跃页面组件的onshow/onhide
259
+ if (isBrowser) {
260
+ const errorHandler = function (args, fromVue) {
261
+ if (global.__mpxAppCbs && global.__mpxAppCbs.error && global.__mpxAppCbs.error.length) {
262
+ global.__mpxAppCbs.error.forEach((cb) => {
263
+ cb.apply(null, args)
264
+ })
265
+ } else if (fromVue) {
266
+ throw args[0]
238
267
  }
239
- option.components[componentName] = component
240
268
  }
241
- }
242
-
243
- if (genericsInfo) {
244
- const genericHash = genericsInfo.hash
245
- global.__mpxGenericsMap[genericHash] = {}
246
- Object.keys(genericsInfo.map).forEach((genericValue) => {
247
- if (componentsMap[genericValue]) {
248
- global.__mpxGenericsMap[genericHash][genericValue] = componentsMap[genericValue]
249
- } else {
250
- console.log(option)
251
- console.warn(`[Mpx runtime warn]: generic value "${genericValue}" must be
252
- registered in parent context!`)
253
- }
269
+ Vue.config.errorHandler = (...args) => {
270
+ return errorHandler(args, true)
271
+ }
272
+ window.addEventListener('error', (event) => {
273
+ return errorHandler([event.error, event])
254
274
  })
255
- }
256
-
257
- if (componentGenerics) {
258
- option.props = option.props || {}
259
- option.props.generichash = String
260
- Object.keys(componentGenerics).forEach((genericName) => {
261
- if (componentGenerics[genericName].default) {
262
- option.props[`generic${genericName}`] = {
263
- type: String,
264
- default: `${genericName}default`
275
+ window.addEventListener('unhandledrejection', (event) => {
276
+ return errorHandler([event.reason, event])
277
+ })
278
+ document.addEventListener('visibilitychange', function () {
279
+ const vnode = global.__mpxRouter && global.__mpxRouter.__mpxActiveVnode
280
+ if (vnode && vnode.componentInstance) {
281
+ const currentPage = vnode.tag.endsWith('mpx-tab-bar-container') ? vnode.componentInstance.$refs.tabBarPage : vnode.componentInstance
282
+ if (document.hidden) {
283
+ if (global.__mpxAppCbs && global.__mpxAppCbs.hide) {
284
+ global.__mpxAppCbs.hide.forEach((cb) => {
285
+ cb()
286
+ })
287
+ }
288
+ if (currentPage) {
289
+ currentPage.mpxPageStatus = 'hide'
290
+ }
291
+ } else {
292
+ if (global.__mpxAppCbs && global.__mpxAppCbs.show) {
293
+ global.__mpxAppCbs.show.forEach((cb) => {
294
+ // todo 实现app.onShow参数
295
+ /* eslint-disable node/no-callback-literal */
296
+ cb({})
297
+ })
298
+ }
299
+ if (currentPage) {
300
+ currentPage.mpxPageStatus = 'show'
301
+ }
265
302
  }
266
- } else {
267
- option.props[`generic${genericName}`] = String
268
303
  }
269
304
  })
270
- }
271
-
272
- if (ctorType === 'page') {
273
- option.__mpxPageConfig = Object.assign({}, global.__mpxPageConfig, pageConfig)
274
- }
275
- if (!hasApp) {
276
- option.directives = { animation }
277
- option.filters = { transRpxStyle }
305
+ // 初始化length
306
+ global.__mpxRouter.__mpxHistoryLength = global.history.length
278
307
  }
279
308
  }
280
309
 
281
- if (option.mixins) {
282
- option.mixins.push(mixin)
283
- } else {
284
- option.mixins = [mixin]
310
+ if (App.onAppInit) {
311
+ Object.assign(option, App.onAppInit() || {})
285
312
  }
286
313
 
287
- if (outputPath) {
288
- option.componentPath = '/' + outputPath
314
+ if (isBrowser && global.__mpxPinia) {
315
+ // 注入pinia
316
+ option.pinia = global.__mpxPinia
289
317
  }
290
- return option
291
- }
292
318
 
293
- export function getComponent (component, extendOptions) {
294
- component = component.__esModule ? component.default : component
295
- // eslint-disable-next-line
296
- if (extendOptions) Object.assign(component, extendOptions)
297
- return component
319
+ const app = new Vue({
320
+ ...option,
321
+ render: (h) => h(App)
322
+ })
323
+ return {
324
+ app,
325
+ ...option
326
+ }
298
327
  }
299
328
 
300
- export function getWxsMixin (wxsModules) {
301
- if (!wxsModules) return {}
302
- return {
303
- created () {
304
- Object.keys(wxsModules).forEach((key) => {
305
- if (key in this) {
306
- console.error(`[Mpx runtime error]: The wxs module key [${key}] exist in the component/page instance already, please check and rename it!`)
307
- } else {
308
- this[key] = wxsModules[key]
309
- }
329
+ export function processAppOption ({ firstPage, pagesMap, componentsMap, App, Vue, VueRouter, tabBarMap, webConfig }) {
330
+ if (!isBrowser) {
331
+ return context => {
332
+ const { app, router, pinia = {} } = createApp({
333
+ App,
334
+ componentsMap,
335
+ Vue,
336
+ pagesMap,
337
+ firstPage,
338
+ VueRouter,
339
+ tabBarMap
310
340
  })
341
+ if (App.onSSRAppCreated) {
342
+ return App.onSSRAppCreated({ pinia, router, app, context })
343
+ } else {
344
+ return new Promise((resolve, reject) => {
345
+ router.push(context.url)
346
+ router.onReady(() => {
347
+ context.rendered = () => {
348
+ context.state = pinia?.state?.value || {}
349
+ }
350
+ resolve(app)
351
+ }, reject)
352
+ })
353
+ }
354
+ }
355
+ } else {
356
+ const { app, pinia } = createApp({
357
+ App,
358
+ componentsMap,
359
+ Vue,
360
+ pagesMap,
361
+ firstPage,
362
+ VueRouter,
363
+ tabBarMap
364
+ })
365
+ if (window.__INITIAL_STATE__ && pinia) {
366
+ pinia.state.value = window.__INITIAL_STATE__
311
367
  }
368
+ app.$mount(webConfig.el || '#app')
312
369
  }
313
370
  }