@mpxjs/webpack-plugin 2.6.103 → 2.7.0-alpha.0

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 (58) hide show
  1. package/lib/dependencies/AppEntryDependency.js +56 -0
  2. package/lib/dependencies/CommonJsVariableDependency.js +74 -0
  3. package/lib/dependencies/DynamicEntryDependency.js +127 -0
  4. package/lib/dependencies/FlagPluginDependency.js +23 -0
  5. package/lib/dependencies/InjectDependency.js +43 -0
  6. package/lib/dependencies/RecordGlobalComponentsDependency.js +50 -0
  7. package/lib/dependencies/RecordStaticResourceDependency.js +47 -0
  8. package/lib/{dependency → dependencies}/ReplaceDependency.js +19 -2
  9. package/lib/dependencies/ResolveDependency.js +83 -0
  10. package/lib/extractor.js +72 -179
  11. package/lib/file-loader.js +7 -19
  12. package/lib/helpers.js +41 -331
  13. package/lib/index.js +475 -365
  14. package/lib/json-compiler/helper.js +152 -0
  15. package/lib/json-compiler/index.js +148 -407
  16. package/lib/json-compiler/plugin.js +134 -0
  17. package/lib/json-compiler/{theme-loader.js → theme.js} +5 -3
  18. package/lib/loader.js +78 -177
  19. package/lib/native-loader.js +40 -70
  20. package/lib/record-loader.js +11 -0
  21. package/lib/{path-loader.js → resolve-loader.js} +0 -0
  22. package/lib/runtime/i18n.wxs +3 -3
  23. package/lib/selector.js +8 -7
  24. package/lib/style-compiler/index.js +14 -15
  25. package/lib/template-compiler/compiler.js +16 -153
  26. package/lib/template-compiler/index.js +46 -132
  27. package/lib/url-loader.js +11 -29
  28. package/lib/utils/add-query.js +1 -1
  29. package/lib/utils/const.js +5 -0
  30. package/lib/utils/emit-file.js +10 -0
  31. package/lib/utils/get-entry-name.js +13 -0
  32. package/lib/utils/is-url-request.js +10 -1
  33. package/lib/utils/normalize.js +0 -13
  34. package/lib/utils/parse-request.js +3 -3
  35. package/lib/utils/set.js +47 -0
  36. package/lib/utils/stringify-loaders-resource.js +25 -0
  37. package/lib/utils/stringify-query.js +4 -0
  38. package/lib/web/processScript.js +3 -3
  39. package/lib/web/processTemplate.js +2 -0
  40. package/lib/wxml/{wxml-loader.js → loader.js} +24 -60
  41. package/lib/wxs/WxsModuleIdsPlugin.js +32 -0
  42. package/lib/wxs/WxsParserPlugin.js +2 -2
  43. package/lib/wxs/WxsPlugin.js +4 -8
  44. package/lib/wxs/WxsTemplatePlugin.js +46 -92
  45. package/lib/wxs/{wxs-i18n-loader.js → i18n-loader.js} +0 -0
  46. package/lib/wxs/{wxs-loader.js → loader.js} +33 -38
  47. package/lib/wxs/{wxs-pre-loader.js → pre-loader.js} +0 -0
  48. package/lib/wxss/loader.js +31 -43
  49. package/lib/wxss/localsLoader.js +1 -5
  50. package/package.json +4 -8
  51. package/lib/content-loader.js +0 -13
  52. package/lib/dependency/ChildCompileDependency.js +0 -24
  53. package/lib/dependency/InjectDependency.js +0 -26
  54. package/lib/dependency/RemovedModuleDependency.js +0 -23
  55. package/lib/dependency/ResolveDependency.js +0 -49
  56. package/lib/plugin-loader.js +0 -287
  57. package/lib/utils/try-require.js +0 -16
  58. package/lib/wxss/getImportPrefix.js +0 -30
@@ -0,0 +1,134 @@
1
+ const async = require('async')
2
+ const JSON5 = require('json5')
3
+ const getEntryName = require('../utils/get-entry-name')
4
+ const FlagPluginDependency = require('../dependencies/FlagPluginDependency')
5
+ const createJSONHelper = require('./helper')
6
+
7
+ module.exports = function (source) {
8
+ // 该loader中会在每次编译中动态添加entry,不能缓存,否则watch不好使
9
+ const nativeCallback = this.async()
10
+
11
+ const mpx = this.getMpx()
12
+
13
+ if (!mpx) {
14
+ return nativeCallback(null, source)
15
+ }
16
+
17
+ this._module.addPresentationalDependency(new FlagPluginDependency())
18
+
19
+ const emitWarning = (msg) => {
20
+ this.emitWarning(
21
+ new Error('[plugin loader][' + this.resource + ']: ' + msg)
22
+ )
23
+ }
24
+
25
+ const emitError = (msg) => {
26
+ this.emitError(
27
+ new Error('[plugin loader][' + this.resource + ']: ' + msg)
28
+ )
29
+ }
30
+
31
+ const {
32
+ processPage,
33
+ processDynamicEntry,
34
+ processComponent,
35
+ processJsExport
36
+ } = createJSONHelper({
37
+ loaderContext: this,
38
+ emitWarning,
39
+ emitError
40
+ })
41
+
42
+ const context = this.context
43
+ const relativePath = this._compilation.outputOptions.publicPath || ''
44
+ const mode = mpx.mode
45
+ const srcMode = mpx.srcMode
46
+ const entryName = getEntryName(this)
47
+ // 最终输出中不需要为plugin.json产生chunk,而是使用extractor输出,删除plugin.json对应的entrypoint
48
+ if (entryName) this._compilation.entries.delete(entryName)
49
+
50
+ // 新模式下plugin.json输出依赖于extractor
51
+ const callback = (err, processOutput) => {
52
+ if (err) return nativeCallback(err)
53
+ let output = `var pluginEntry = ${JSON.stringify(pluginEntry, null, 2)};\n`
54
+ if (processOutput) output = processOutput(output)
55
+ output += `module.exports = JSON.stringify(pluginEntry, null, 2);\n`
56
+ nativeCallback(null, output)
57
+ }
58
+
59
+ let pluginEntry
60
+ try {
61
+ pluginEntry = JSON5.parse(source)
62
+ } catch (err) {
63
+ return callback(err)
64
+ }
65
+
66
+ const processMain = (main, callback) => {
67
+ if (!main) return callback()
68
+ processJsExport(main, context, '', (err, entry) => {
69
+ if (err) return callback(err)
70
+ pluginEntry.main = entry
71
+ callback()
72
+ })
73
+ }
74
+
75
+ const processComponents = (components, callback) => {
76
+ if (!components) return callback()
77
+ async.eachOf(components, (component, name, callback) => {
78
+ processComponent(component, context, { relativePath }, (err, entry) => {
79
+ if (err) return callback(err)
80
+ pluginEntry.publicComponents[name] = entry
81
+ callback()
82
+ })
83
+ }, callback)
84
+ }
85
+
86
+ const processPages = (pages, callback) => {
87
+ if (!pages) return callback()
88
+ if (srcMode === 'ali') {
89
+ const reversedMap = {}
90
+ const publicPages = pluginEntry.publicPages || {}
91
+ Object.keys(publicPages).forEach((key) => {
92
+ const item = publicPages[key]
93
+ reversedMap[item] = key
94
+ })
95
+ pages = pages.reduce((page, target, index) => {
96
+ const key = reversedMap[page] || `__private_page_${index}__`
97
+ target[key] = page
98
+ }, {})
99
+ }
100
+
101
+ if (mode === 'ali') {
102
+ pluginEntry.publicPages = {}
103
+ pluginEntry.pages = []
104
+ }
105
+
106
+ async.eachOf(pages, (page, key) => {
107
+ processPage(page, context, '', (err, entry) => {
108
+ if (err) return callback(err)
109
+ pages[key] = entry
110
+ if (mode === 'ali') {
111
+ pluginEntry.pages.push(entry)
112
+ if (!/^__private_page_\d+__$/.test(key)) {
113
+ pluginEntry.publicPages[key] = entry
114
+ }
115
+ } else {
116
+ pluginEntry.pages[key] = entry
117
+ }
118
+ callback()
119
+ })
120
+ })
121
+ }
122
+
123
+ async.parallel([
124
+ (callback) => {
125
+ return processMain(pluginEntry.main, callback)
126
+ }, (callback) => {
127
+ return processComponents(pluginEntry.publicComponents, callback)
128
+ }, (callback) => {
129
+ return processPages(pluginEntry.publicPages, callback)
130
+ }
131
+ ], (err) => {
132
+ return callback(err, processDynamicEntry)
133
+ })
134
+ }
@@ -8,9 +8,11 @@ function isFile (request) {
8
8
  }
9
9
 
10
10
  module.exports = function (raw) {
11
- const options = loaderUtils.getOptions(this) || {}
12
- const isUrlRequest = r => isUrlRequestRaw(r, options.root)
13
- const urlToRequest = r => loaderUtils.urlToRequest(r, options.root)
11
+ const mpx = this.getMpx()
12
+ const root = mpx.projectRoot
13
+ const externals = mpx.externals
14
+ const isUrlRequest = r => isUrlRequestRaw(r, root, externals)
15
+ const urlToRequest = r => loaderUtils.urlToRequest(r, root)
14
16
 
15
17
  const json = JSON5.parse(raw)
16
18
  let output = `var json = ${JSON.stringify(json, null, 2)};\n`
package/lib/loader.js CHANGED
@@ -2,7 +2,6 @@ const JSON5 = require('json5')
2
2
  const parseComponent = require('./parser')
3
3
  const createHelpers = require('./helpers')
4
4
  const loaderUtils = require('loader-utils')
5
- const InjectDependency = require('./dependency/InjectDependency')
6
5
  const parseRequest = require('./utils/parse-request')
7
6
  const matchCondition = require('./utils/match-condition')
8
7
  const fixUsingComponent = require('./utils/fix-using-component')
@@ -14,12 +13,13 @@ const processStyles = require('./web/processStyles')
14
13
  const processTemplate = require('./web/processTemplate')
15
14
  const readJsonForSrc = require('./utils/read-json-for-src')
16
15
  const normalize = require('./utils/normalize')
17
- const getMainCompilation = require('./utils/get-main-compilation')
16
+ const getEntryName = require('./utils/get-entry-name')
17
+ const AppEntryDependency = require('./dependencies/AppEntryDependency')
18
+
18
19
  module.exports = function (content) {
19
20
  this.cacheable()
20
21
 
21
- const mainCompilation = getMainCompilation(this._compilation)
22
- const mpx = mainCompilation.__mpx__
22
+ const mpx = this.getMpx()
23
23
  if (!mpx) {
24
24
  return content
25
25
  }
@@ -41,19 +41,11 @@ module.exports = function (content) {
41
41
 
42
42
  // 支持资源query传入page或component支持页面/组件单独编译
43
43
  if ((queryObj.component && !componentsMap[resourcePath]) || (queryObj.page && !pagesMap[resourcePath])) {
44
- let entryChunkName
45
- const rawRequest = this._module.rawRequest
46
- const _preparedEntrypoints = this._compilation._preparedEntrypoints
47
- for (let i = 0; i < _preparedEntrypoints.length; i++) {
48
- if (rawRequest === _preparedEntrypoints[i].request) {
49
- entryChunkName = _preparedEntrypoints[i].name
50
- break
51
- }
52
- }
44
+ const entryName = getEntryName(this)
53
45
  if (queryObj.component) {
54
- componentsMap[resourcePath] = entryChunkName || 'noEntryComponent'
46
+ componentsMap[resourcePath] = entryName || 'noEntryComponent'
55
47
  } else {
56
- pagesMap[resourcePath] = entryChunkName || 'noEntryPage'
48
+ pagesMap[resourcePath] = entryName || 'noEntryPage'
57
49
  }
58
50
  }
59
51
 
@@ -65,31 +57,19 @@ module.exports = function (content) {
65
57
  // component
66
58
  ctorType = 'component'
67
59
  }
60
+
61
+ if (ctorType === 'app') {
62
+ const appName = getEntryName(this)
63
+ this._module.addPresentationalDependency(new AppEntryDependency(resourcePath, appName))
64
+ }
65
+
68
66
  const loaderContext = this
69
67
  const stringifyRequest = r => loaderUtils.stringifyRequest(loaderContext, r)
70
68
  const isProduction = this.minimize || process.env.NODE_ENV === 'production'
71
- const options = loaderUtils.getOptions(this) || {}
72
- const processSrcQuery = (src, type) => {
73
- const localQuery = Object.assign({}, queryObj)
74
- // style src会被特殊处理为全局复用样式,不添加resourcePath,添加isStatic及issuerResource
75
- if (type === 'styles') {
76
- localQuery.isStatic = true
77
- localQuery.issuerResource = this.resource
78
- } else {
79
- localQuery.resourcePath = resourcePath
80
- }
81
- if (type === 'json') {
82
- localQuery.__component = true
83
- }
84
- return addQuery(src, localQuery)
85
- }
86
69
 
87
70
  const filePath = resourcePath
88
71
 
89
- let moduleId = 'm' + mpx.pathHash(filePath)
90
- if (ctorType === 'app') {
91
- moduleId = 'mpx-app-scope'
92
- }
72
+ const moduleId = 'm' + mpx.pathHash(filePath)
93
73
 
94
74
  const parts = parseComponent(content, {
95
75
  filePath,
@@ -120,8 +100,7 @@ module.exports = function (content) {
120
100
  if (vueContentCache.has(filePath)) {
121
101
  return callback(null, vueContentCache.get(filePath))
122
102
  }
123
- // 只有ali才可能需要scoped
124
- const hasScoped = (parts.styles.some(({ scoped }) => scoped) || autoScope) && mode === 'ali'
103
+ const hasScoped = parts.styles.some(({ scoped }) => scoped) || autoScope
125
104
  const templateAttrs = parts.template && parts.template.attrs
126
105
  const hasComment = templateAttrs && templateAttrs.comments
127
106
  const isNative = false
@@ -145,24 +124,6 @@ module.exports = function (content) {
145
124
  }
146
125
  }
147
126
 
148
- const {
149
- getRequire,
150
- getRequireForSrc,
151
- getRequestString,
152
- getSrcRequestString
153
- } = createHelpers({
154
- loaderContext,
155
- options,
156
- moduleId,
157
- hasScoped,
158
- ctorType,
159
- hasComment,
160
- usingComponents,
161
- srcMode,
162
- isNative,
163
- projectRoot
164
- })
165
-
166
127
  // 处理mode为web时输出vue格式文件
167
128
  if (mode === 'web') {
168
129
  if (ctorType === 'app' && !queryObj.app) {
@@ -187,6 +148,7 @@ module.exports = function (content) {
187
148
  async.parallel([
188
149
  (callback) => {
189
150
  processTemplate(parts.template, {
151
+ hasScoped,
190
152
  hasComment,
191
153
  isNative,
192
154
  mode,
@@ -240,7 +202,6 @@ module.exports = function (content) {
240
202
  srcMode,
241
203
  loaderContext,
242
204
  isProduction,
243
- getRequireForSrc,
244
205
  i18n,
245
206
  componentGenerics,
246
207
  projectRoot,
@@ -264,36 +225,23 @@ module.exports = function (content) {
264
225
  })
265
226
  }
266
227
 
267
- // 触发webpack global var 注入
268
- output += 'global.currentModuleId\n'
228
+ const {
229
+ getRequire
230
+ } = createHelpers(loaderContext)
269
231
 
270
- // todo loader中inject dep比较危险,watch模式下不一定靠谱,可考虑将import改为require然后通过修改loader内容注入
271
232
  // 注入模块id及资源路径
272
- let globalInjectCode = `global.currentModuleId = ${JSON.stringify(moduleId)}\n`
233
+ output += `global.currentModuleId = ${JSON.stringify(moduleId)}\n`
273
234
  if (!isProduction) {
274
- globalInjectCode += `global.currentResource = ${JSON.stringify(filePath)}\n`
235
+ output += `global.currentResource = ${JSON.stringify(filePath)}\n`
275
236
  }
276
- if (ctorType === 'app' && i18n && !mpx.forceDisableInject) {
277
- globalInjectCode += `global.i18n = ${JSON.stringify({ locale: i18n.locale, version: 0 })}\n`
237
+ if (ctorType === 'app' && i18n) {
238
+ output += `global.i18n = ${JSON.stringify({ locale: i18n.locale, version: 0 })}\n`
278
239
 
279
- const i18nMethodsVar = 'i18nMethods'
280
240
  const i18nWxsPath = normalize.lib('runtime/i18n.wxs')
281
- const i18nWxsLoaderPath = normalize.lib('wxs/wxs-i18n-loader.js')
241
+ const i18nWxsLoaderPath = normalize.lib('wxs/i18n-loader.js')
282
242
  const i18nWxsRequest = i18nWxsLoaderPath + '!' + i18nWxsPath
283
- const expression = `require(${loaderUtils.stringifyRequest(loaderContext, i18nWxsRequest)})`
284
- const deps = []
285
- this._module.parser.parse(expression, {
286
- current: {
287
- addDependency: dep => {
288
- dep.userRequest = i18nMethodsVar
289
- deps.push(dep)
290
- }
291
- },
292
- module: this._module
293
- })
294
- this._module.addVariable(i18nMethodsVar, expression, deps)
295
243
 
296
- globalInjectCode += `global.i18nMethods = ${i18nMethodsVar}\n`
244
+ output += `global.i18nMethods = require(${loaderUtils.stringifyRequest(loaderContext, i18nWxsRequest)})\n`
297
245
  }
298
246
  // 注入构造函数
299
247
  let ctor = 'App'
@@ -307,95 +255,48 @@ module.exports = function (content) {
307
255
  } else if (ctorType === 'component') {
308
256
  ctor = 'Component'
309
257
  }
310
- globalInjectCode += `global.currentCtor = ${ctor}\n`
311
- globalInjectCode += `global.currentCtorType = ${JSON.stringify(ctor.replace(/^./, (match) => {
258
+ output += `global.currentCtor = ${ctor}\n`
259
+ output += `global.currentCtorType = ${JSON.stringify(ctor.replace(/^./, (match) => {
312
260
  return match.toLowerCase()
313
261
  }))}\n`
314
262
 
315
- // <script>
316
- output += '/* script */\n'
317
- let scriptSrcMode = srcMode
318
- const script = parts.script
319
- if (script) {
320
- scriptSrcMode = script.mode || scriptSrcMode
321
- let scriptRequestString
322
- if (script.src) {
323
- // 传入resourcePath以确保后续处理中能够识别src引入的资源为组件主资源
324
- script.src = processSrcQuery(script.src, 'script')
325
- scriptRequestString = getSrcRequestString('script', script)
326
- } else {
327
- scriptRequestString = getRequestString('script', script)
328
- }
329
- if (scriptRequestString) {
330
- output += 'export * from ' + scriptRequestString + '\n\n'
331
- if (ctorType === 'app') mpx.appScriptRawRequest = JSON.parse(scriptRequestString)
332
- }
333
- } else {
334
- switch (ctorType) {
335
- case 'app':
336
- output += 'import {createApp} from "@mpxjs/core"\n' +
337
- 'createApp({})\n'
338
- break
339
- case 'page':
340
- output += 'import {createPage} from "@mpxjs/core"\n' +
341
- 'createPage({})\n'
342
- break
343
- case 'component':
344
- output += 'import {createComponent} from "@mpxjs/core"\n' +
345
- 'createComponent({})\n'
346
- }
347
- output += '\n'
348
- }
263
+ // template
264
+ output += '/* template */\n'
265
+ const template = parts.template
349
266
 
350
- if (scriptSrcMode) {
351
- globalInjectCode += `global.currentSrcMode = ${JSON.stringify(scriptSrcMode)}\n`
267
+ if (template) {
268
+ const extraOptions = {
269
+ hasScoped,
270
+ hasComment,
271
+ isNative,
272
+ moduleId,
273
+ usingComponents
274
+ // 添加babel处理渲染函数中可能包含的...展开运算符
275
+ // 由于...运算符应用范围极小以及babel成本极高,先关闭此特性后续看情况打开
276
+ // needBabel: true
277
+ }
278
+ if (template.src) extraOptions.resourcePath = resourcePath
279
+ // 基于global.currentInject来注入模板渲染函数和refs等信息
280
+ output += getRequire('template', template, extraOptions) + '\n'
352
281
  }
353
282
 
354
283
  // styles
355
284
  output += '/* styles */\n'
356
- let cssModules
357
285
  if (parts.styles.length) {
358
- let styleInjectionCode = ''
359
286
  parts.styles.forEach((style, i) => {
360
- let scoped = hasScoped ? (style.scoped || autoScope) : false
361
- let requireString
287
+ const scoped = style.scoped || autoScope
288
+ const extraOptions = {
289
+ moduleId,
290
+ scoped
291
+ }
362
292
  // require style
363
293
  if (style.src) {
364
- style.src = processSrcQuery(style.src, 'styles')
365
- requireString = getRequireForSrc('styles', style, -1, scoped)
366
- } else {
367
- requireString = getRequire('styles', style, i, scoped)
368
- }
369
- const hasStyleLoader = requireString.indexOf('style-loader') > -1
370
- const invokeStyle = code => `${code}\n`
371
-
372
- const moduleName = style.module === true ? '$style' : style.module
373
- // setCssModule
374
- if (moduleName) {
375
- if (!cssModules) {
376
- cssModules = {}
377
- }
378
- if (moduleName in cssModules) {
379
- loaderContext.emitError(
380
- 'CSS module name "' + moduleName + '" is not unique!'
381
- )
382
- styleInjectionCode += invokeStyle(requireString)
383
- } else {
384
- cssModules[moduleName] = true
385
-
386
- if (!hasStyleLoader) {
387
- requireString += '.locals'
388
- }
389
-
390
- styleInjectionCode += invokeStyle(
391
- 'this["' + moduleName + '"] = ' + requireString
392
- )
393
- }
394
- } else {
395
- styleInjectionCode += invokeStyle(requireString)
294
+ // style src会被特殊处理为全局复用样式,不添加resourcePath,添加isStatic及issuerResource
295
+ extraOptions.isStatic = true
296
+ extraOptions.issuerFile = mpx.getExtractedFile(this.resource)
396
297
  }
298
+ output += getRequire('styles', style, extraOptions, i) + '\n'
397
299
  })
398
- output += styleInjectionCode + '\n'
399
300
  } else if (ctorType === 'app' && mode === 'ali') {
400
301
  output += getRequire('styles', {}) + '\n'
401
302
  }
@@ -404,34 +305,34 @@ module.exports = function (content) {
404
305
  output += '/* json */\n'
405
306
  // 给予json默认值, 确保生成json request以自动补全json
406
307
  const json = parts.json || {}
407
- if (json.src) {
408
- json.src = processSrcQuery(json.src, 'json')
409
- output += getRequireForSrc('json', json) + '\n\n'
410
- } else {
411
- output += getRequire('json', json) + '\n\n'
412
- }
308
+ output += getRequire('json', json, json.src && { resourcePath }) + '\n'
413
309
 
414
- // template
415
- output += '/* template */\n'
416
- const template = parts.template
417
-
418
- if (template) {
419
- if (template.src) {
420
- template.src = processSrcQuery(template.src, 'template')
421
- output += getRequireForSrc('template', template) + '\n\n'
422
- } else {
423
- output += getRequire('template', template) + '\n\n'
310
+ // script
311
+ output += '/* script */\n'
312
+ let scriptSrcMode = srcMode
313
+ const script = parts.script
314
+ if (script) {
315
+ scriptSrcMode = script.mode || scriptSrcMode
316
+ if (scriptSrcMode) output += `global.currentSrcMode = ${JSON.stringify(scriptSrcMode)}\n`
317
+ const extraOptions = {}
318
+ if (script.src) extraOptions.resourcePath = resourcePath
319
+ output += getRequire('script', script, extraOptions) + '\n'
320
+ } else {
321
+ switch (ctorType) {
322
+ case 'app':
323
+ output += 'import {createApp} from "@mpxjs/core"\n' +
324
+ 'createApp({})\n'
325
+ break
326
+ case 'page':
327
+ output += 'import {createPage} from "@mpxjs/core"\n' +
328
+ 'createPage({})\n'
329
+ break
330
+ case 'component':
331
+ output += 'import {createComponent} from "@mpxjs/core"\n' +
332
+ 'createComponent({})\n'
424
333
  }
334
+ output += '\n'
425
335
  }
426
-
427
- if (!mpx.forceDisableInject) {
428
- const dep = new InjectDependency({
429
- content: globalInjectCode,
430
- index: -3
431
- })
432
- this._module.addDependency(dep)
433
- }
434
-
435
336
  callback(null, output)
436
337
  }
437
338
  ], callback)