@mpxjs/webpack-plugin 2.8.48 → 2.8.50

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.
@@ -0,0 +1,51 @@
1
+ const ModuleDependency = require('webpack/lib/dependencies/ModuleDependency')
2
+ const makeSerializable = require('webpack/lib/util/makeSerializable')
3
+
4
+ class CommonJsExtractDependency extends ModuleDependency {
5
+ constructor (request, range) {
6
+ super(request)
7
+ this.range = range
8
+ }
9
+
10
+ get type () {
11
+ return 'mpx cjs extract'
12
+ }
13
+
14
+ get category () {
15
+ return 'commonjs'
16
+ }
17
+ }
18
+
19
+ CommonJsExtractDependency.Template = class CommonJsExtractDependencyTemplate extends (
20
+ ModuleDependency.Template
21
+ ) {
22
+ apply (
23
+ dep,
24
+ source,
25
+ {
26
+ runtimeTemplate,
27
+ moduleGraph,
28
+ chunkGraph,
29
+ runtimeRequirements
30
+ }
31
+ ) {
32
+ let content = ''
33
+ if (!dep.weak) {
34
+ content = runtimeTemplate.moduleExports({
35
+ module: moduleGraph.getModule(dep),
36
+ chunkGraph,
37
+ request: dep.request,
38
+ weak: dep.weak,
39
+ runtimeRequirements
40
+ })
41
+ }
42
+ source.replace(dep.range[0], dep.range[1] - 1, content)
43
+ }
44
+ }
45
+
46
+ makeSerializable(
47
+ CommonJsExtractDependency,
48
+ '@mpxjs/webpack-plugin/lib/dependencies/CommonJsExtractDependency'
49
+ )
50
+
51
+ module.exports = CommonJsExtractDependency
package/lib/extractor.js CHANGED
@@ -116,5 +116,6 @@ module.exports.pitch = async function (remainingRequest) {
116
116
  }
117
117
  }
118
118
 
119
+ if (!resultSource) buildInfo.isEmpty = true
119
120
  return resultSource
120
121
  }
package/lib/helpers.js CHANGED
@@ -20,7 +20,15 @@ module.exports = function createHelpers (loaderContext) {
20
20
  const { mode, env } = loaderContext.getMpx() || {}
21
21
 
22
22
  function getRequire (type, part, extraOptions, index) {
23
- return 'require(' + getRequestString(type, part, extraOptions, index) + ')'
23
+ let extract = false
24
+ switch (type) {
25
+ // eslint-disable-next-line no-fallthrough
26
+ case 'json':
27
+ case 'styles':
28
+ case 'template':
29
+ extract = true
30
+ }
31
+ return (extract ? 'require.extract(' : 'require(') + getRequestString(type, part, extraOptions, index) + ')'
24
32
  }
25
33
 
26
34
  function getImport (type, part, extraOptions, index) {
package/lib/index.js CHANGED
@@ -8,6 +8,7 @@ const ReplaceDependency = require('./dependencies/ReplaceDependency')
8
8
  const NullFactory = require('webpack/lib/NullFactory')
9
9
  const CommonJsVariableDependency = require('./dependencies/CommonJsVariableDependency')
10
10
  const CommonJsAsyncDependency = require('./dependencies/CommonJsAsyncDependency')
11
+ const CommonJsExtractDependency = require('./dependencies/CommonJsExtractDependency')
11
12
  const harmonySpecifierTag = require('webpack/lib/dependencies/HarmonyImportDependencyParserPlugin').harmonySpecifierTag
12
13
  const NormalModule = require('webpack/lib/NormalModule')
13
14
  const EntryPlugin = require('webpack/lib/EntryPlugin')
@@ -124,6 +125,7 @@ class MpxWebpackPlugin {
124
125
  options.resolveMode = options.resolveMode || 'webpack'
125
126
  options.writeMode = options.writeMode || 'changed'
126
127
  options.autoScopeRules = options.autoScopeRules || {}
128
+ options.renderOptimizeRules = options.renderOptimizeRules || {}
127
129
  options.autoVirtualHostRules = options.autoVirtualHostRules || {}
128
130
  options.forceDisableProxyCtor = options.forceDisableProxyCtor || false
129
131
  options.transMpxRules = options.transMpxRules || {
@@ -405,13 +407,13 @@ class MpxWebpackPlugin {
405
407
  name: 'MpxPartialCompilePlugin',
406
408
  stage: -100
407
409
  }, (obj, resolverContext, callback) => {
408
- if (obj.path.startsWith(require.resolve('./json-compiler/default-page.mpx'))) {
410
+ if (obj.path.startsWith(require.resolve('./runtime/components/wx/default-page.mpx'))) {
409
411
  return callback(null, obj)
410
412
  }
411
413
  if (isResolvingPage(obj) && !matchCondition(obj.path, this.options.partialCompile)) {
412
414
  const infix = obj.query ? '&' : '?'
413
415
  obj.query += `${infix}resourcePath=${obj.path}`
414
- obj.path = require.resolve('./json-compiler/default-page.mpx')
416
+ obj.path = require.resolve('./runtime/components/wx/default-page.mpx')
415
417
  }
416
418
  callback(null, obj)
417
419
  })
@@ -554,6 +556,9 @@ class MpxWebpackPlugin {
554
556
  compilation.dependencyFactories.set(CommonJsAsyncDependency, normalModuleFactory)
555
557
  compilation.dependencyTemplates.set(CommonJsAsyncDependency, new CommonJsAsyncDependency.Template())
556
558
 
559
+ compilation.dependencyFactories.set(CommonJsExtractDependency, normalModuleFactory)
560
+ compilation.dependencyTemplates.set(CommonJsExtractDependency, new CommonJsExtractDependency.Template())
561
+
557
562
  compilation.dependencyFactories.set(RecordVueContentDependency, new NullFactory())
558
563
  compilation.dependencyTemplates.set(RecordVueContentDependency, new RecordVueContentDependency.Template())
559
564
  })
@@ -628,6 +633,7 @@ class MpxWebpackPlugin {
628
633
  appTitle: 'Mpx homepage',
629
634
  attributes: this.options.attributes,
630
635
  externals: this.options.externals,
636
+ renderOptimizeRules: this.options.renderOptimizeRules,
631
637
  useRelativePath: this.options.useRelativePath,
632
638
  removedChunks: [],
633
639
  forceProxyEventRules: this.options.forceProxyEventRules,
@@ -923,6 +929,17 @@ class MpxWebpackPlugin {
923
929
  })
924
930
 
925
931
  compilation.hooks.finishModules.tap('MpxWebpackPlugin', (modules) => {
932
+ // 移除extractor抽取后的空模块
933
+ for (const module of modules) {
934
+ if (module.buildInfo.isEmpty) {
935
+ for (const connection of moduleGraph.getIncomingConnections(module)) {
936
+ if (connection.dependency.type === 'mpx cjs extract') {
937
+ connection.weak = true
938
+ connection.dependency.weak = true
939
+ }
940
+ }
941
+ }
942
+ }
926
943
  // 自动跟进分包配置修改splitChunksPlugin配置
927
944
  if (splitChunksPlugin) {
928
945
  let needInit = false
@@ -1096,6 +1113,31 @@ class MpxWebpackPlugin {
1096
1113
  stage: -1000
1097
1114
  }, (expr, calleeMembers, callExpr) => requireAsyncHandler(callExpr, calleeMembers, expr.arguments))
1098
1115
 
1116
+ const requireExtractHandler = (expr, members, args) => {
1117
+ if (members[0] === 'extract') {
1118
+ const request = expr.arguments[0].value
1119
+ const range = expr.range
1120
+ const dep = new CommonJsExtractDependency(request, range)
1121
+ parser.state.current.addDependency(dep)
1122
+ if (args) parser.walkExpressions(args)
1123
+ return true
1124
+ }
1125
+ }
1126
+
1127
+ parser.hooks.callMemberChain
1128
+ .for('require')
1129
+ .tap({
1130
+ name: 'MpxWebpackPlugin',
1131
+ stage: -2000
1132
+ }, (expr, members) => requireExtractHandler(expr, members))
1133
+
1134
+ parser.hooks.callMemberChainOfCallMemberChain
1135
+ .for('require')
1136
+ .tap({
1137
+ name: 'MpxWebpackPlugin',
1138
+ stage: -2000
1139
+ }, (expr, calleeMembers, callExpr) => requireExtractHandler(callExpr, calleeMembers, expr.arguments))
1140
+
1099
1141
  // hack babel polyfill global
1100
1142
  parser.hooks.statementIf.tap('MpxWebpackPlugin', (expr) => {
1101
1143
  if (/core-js.+microtask/.test(parser.state.module.resource)) {
@@ -22,6 +22,7 @@ module.exports = function createJSONHelper ({ loaderContext, emitWarning, custom
22
22
 
23
23
  const isUrlRequest = r => isUrlRequestRaw(r, root, externals)
24
24
  const urlToRequest = r => loaderUtils.urlToRequest(r)
25
+ const isScript = ext => /\.(ts|js)$/.test(ext)
25
26
 
26
27
  const dynamicEntryMap = new Map()
27
28
 
@@ -73,7 +74,7 @@ module.exports = function createJSONHelper ({ loaderContext, emitWarning, custom
73
74
  const resourceName = path.join(parsed.dir, parsed.name)
74
75
 
75
76
  if (!outputPath) {
76
- if (ext === '.js' && resourceName.includes('node_modules') && mode !== 'web') {
77
+ if (isScript(ext) && resourceName.includes('node_modules') && mode !== 'web') {
77
78
  let root = info.descriptionFileRoot
78
79
  let name = 'nativeComponent'
79
80
  if (info.descriptionFileData) {
@@ -91,7 +92,7 @@ module.exports = function createJSONHelper ({ loaderContext, emitWarning, custom
91
92
  outputPath = getOutputPath(resourcePath, 'component')
92
93
  }
93
94
  }
94
- if (ext === '.js' && mode !== 'web') {
95
+ if (isScript(ext) && mode !== 'web') {
95
96
  resource = `!!${nativeLoaderPath}!${resource}`
96
97
  }
97
98
 
@@ -131,7 +132,7 @@ module.exports = function createJSONHelper ({ loaderContext, emitWarning, custom
131
132
  outputPath = /^(.*?)(\.[^.]*)?$/.exec(relative)[1]
132
133
  }
133
134
  }
134
- if (ext === '.js' && mode !== 'web') {
135
+ if (isScript(ext) && mode !== 'web') {
135
136
  resource = `!!${nativeLoaderPath}!${resource}`
136
137
  }
137
138
  const entry = getDynamicEntry(resource, 'page', outputPath, tarRoot, publicPath + tarRoot)
@@ -250,7 +250,7 @@ module.exports = function (content) {
250
250
  const localPages = []
251
251
  const subPackagesCfg = {}
252
252
  const pageKeySet = new Set()
253
- const defaultPagePath = require.resolve('./default-page.mpx')
253
+ const defaultPagePath = require.resolve('../runtime/components/wx/default-page.mpx')
254
254
  const processPages = (pages, context, tarRoot = '', callback) => {
255
255
  if (pages) {
256
256
  const pagesCache = []
@@ -8,7 +8,7 @@ const async = require('async')
8
8
  const { matchCondition } = require('./utils/match-condition')
9
9
  const { JSON_JS_EXT } = require('./utils/const')
10
10
  const getRulesRunner = require('./platform')
11
-
11
+ // todo native-loader考虑与mpx-loader或加强复用,原生组件约等于4个区块都为src的.mpx文件
12
12
  module.exports = function (content) {
13
13
  this.cacheable()
14
14
 
@@ -44,6 +44,8 @@ module.exports = function (content) {
44
44
  scss: '.scss'
45
45
  }
46
46
 
47
+ const TS_EXT = '.ts'
48
+
47
49
  let useJSONJS = false
48
50
  let cssLang = ''
49
51
  const hasScoped = (queryObj.scoped || autoScope) && mode === 'ali'
@@ -54,7 +56,7 @@ module.exports = function (content) {
54
56
  this.resolve(parsed.dir, resourceName + extName, callback)
55
57
  }
56
58
 
57
- function checkCSSLangFiles (callback) {
59
+ function checkCSSLangFile (callback) {
58
60
  const langs = mpx.nativeConfig.cssLangs || ['less', 'stylus', 'scss', 'sass']
59
61
  const results = []
60
62
  async.eachOf(langs, function (lang, i, callback) {
@@ -89,6 +91,15 @@ module.exports = function (content) {
89
91
  })
90
92
  }
91
93
 
94
+ function checkTSFile (callback) {
95
+ checkFileExists(TS_EXT, (err, result) => {
96
+ if (!err && result) {
97
+ typeResourceMap.script = result
98
+ }
99
+ callback()
100
+ })
101
+ }
102
+
92
103
  const emitWarning = (msg) => {
93
104
  this.emitWarning(
94
105
  new Error('[native-loader][' + this.resource + ']: ' + msg)
@@ -105,15 +116,16 @@ module.exports = function (content) {
105
116
  async.waterfall([
106
117
  (callback) => {
107
118
  async.parallel([
108
- checkCSSLangFiles,
109
- checkJSONJSFile
119
+ checkCSSLangFile,
120
+ checkJSONJSFile,
121
+ checkTSFile
110
122
  ], (err) => {
111
123
  callback(err)
112
124
  })
113
125
  },
114
126
  (callback) => {
115
127
  async.forEachOf(typeExtMap, (ext, key, callback) => {
116
- // 检测到jsonjs或cssLang时跳过对应类型文件检测
128
+ // 对应资源存在预处理类型文件时跳过对应的标准文件检测
117
129
  if (typeResourceMap[key]) {
118
130
  return callback()
119
131
  }
@@ -3,6 +3,7 @@ const normalizeTest = require('../normalize-test')
3
3
  const changeKey = require('../change-key')
4
4
  const normalize = require('../../../utils/normalize')
5
5
  const { capitalToHyphen } = require('../../../utils/string')
6
+ const { isOriginTag } = require('../../../utils/dom-tag-config')
6
7
 
7
8
  const mpxViewPath = normalize.lib('runtime/components/ali/mpx-view.mpx')
8
9
  const mpxTextPath = normalize.lib('runtime/components/ali/mpx-text.mpx')
@@ -70,6 +71,19 @@ module.exports = function getSpec ({ warn, error }) {
70
71
  return input
71
72
  }
72
73
 
74
+ // 校验输出支付宝 componentGenerics 配置的正确性
75
+ function aliComponentGenericsValidate (input) {
76
+ const componentGenerics = input.componentGenerics
77
+ if (componentGenerics && typeof componentGenerics === 'object') {
78
+ Object.keys(componentGenerics).forEach(key => {
79
+ if (!componentGenerics[key].default) {
80
+ error(`Ali environment componentGenerics need to specify a default custom component! please check the configuration of component ${key}`)
81
+ }
82
+ })
83
+ }
84
+ return input
85
+ }
86
+
73
87
  function fillGlobalComponents (input, { globalComponents }) {
74
88
  if (globalComponents) {
75
89
  Object.assign(globalComponents, input.usingComponents)
@@ -112,10 +126,30 @@ module.exports = function getSpec ({ warn, error }) {
112
126
  }
113
127
  }
114
128
 
129
+ /**
130
+ * 将小程序代码中使用的与原生 HTML tag 同名组件进行转化,以解决与原生tag命名冲突问题。
131
+ * @param {string} type usingComponents
132
+ * @returns input
133
+ */
134
+ function webHTMLTagProcesser (type) {
135
+ return function (input) {
136
+ const usingComponents = input[type]
137
+ if (usingComponents) {
138
+ Object.keys(usingComponents).forEach(tag => {
139
+ if (isOriginTag(tag)) {
140
+ usingComponents[`mpx-com-${tag}`] = usingComponents[tag]
141
+ delete usingComponents[tag]
142
+ }
143
+ })
144
+ }
145
+ return input
146
+ }
147
+ }
148
+
115
149
  const componentRules = [
116
150
  {
117
151
  test: 'componentGenerics',
118
- ali: deletePath(true)
152
+ ali: aliComponentGenericsValidate
119
153
  },
120
154
  {
121
155
  test: 'componentPlaceholder',
@@ -124,6 +158,10 @@ module.exports = function getSpec ({ warn, error }) {
124
158
  tt: deletePath(),
125
159
  jd: deletePath()
126
160
  },
161
+ {
162
+ test: 'usingComponents',
163
+ web: webHTMLTagProcesser('usingComponents')
164
+ },
127
165
  {
128
166
  test: 'usingComponents',
129
167
  ali: componentNameCapitalToHyphen('usingComponents'),
@@ -224,7 +262,7 @@ module.exports = function getSpec ({ warn, error }) {
224
262
  }
225
263
 
226
264
  const spec = {
227
- supportedModes: ['ali', 'swan', 'qq', 'tt', 'jd', 'qa', 'dd'],
265
+ supportedModes: ['ali', 'swan', 'qq', 'tt', 'jd', 'qa', 'dd', 'web'],
228
266
  normalizeTest,
229
267
  page: [
230
268
  ...windowRules,
@@ -325,6 +363,10 @@ module.exports = function getSpec ({ warn, error }) {
325
363
  tt: deletePath(),
326
364
  jd: deletePath(true)
327
365
  },
366
+ {
367
+ test: 'usingComponents',
368
+ web: webHTMLTagProcesser('usingComponents')
369
+ },
328
370
  {
329
371
  test: 'usingComponents',
330
372
  ali: componentNameCapitalToHyphen('usingComponents'),
@@ -32,7 +32,8 @@ module.exports = function runRules (rules = [], input, options = {}) {
32
32
  if (result !== undefined) {
33
33
  input = result
34
34
  }
35
- if (!waterfall) break
35
+ // rule 内外 waterfall 均为 false 时跳过
36
+ if (!rule.waterfall && !waterfall) break
36
37
  }
37
38
  }
38
39
  return input
@@ -11,6 +11,8 @@ module.exports = function normalizeComponentRules (cfgs, spec) {
11
11
  if (cfg.test) {
12
12
  result.test = cfg.test
13
13
  }
14
+ // 透传 waterfall 信息
15
+ if (cfg.waterfall) result.waterfall = cfg.waterfall
14
16
  const supportedModes = cfg.supportedModes || spec.supportedModes
15
17
  // 合并component-config中组件的event 与index中公共的event规则
16
18
  const eventRules = (cfg.event || []).concat(spec.event.rules)
@@ -0,0 +1,17 @@
1
+ const { isOriginTag } = require('../../../../utils/dom-tag-config')
2
+
3
+ module.exports = function () {
4
+ return {
5
+ waterfall: true,
6
+ test: (input) => isOriginTag(input),
7
+ // 处理原生tag
8
+ web (tag, data = {}) {
9
+ // @see packages/webpack-plugin/lib/platform/json/wx/index.js webHTMLTagProcesser
10
+ const newTag = `mpx-com-${tag}`
11
+ const usingComponents = data.usingComponents || []
12
+ // 存在同名组件,则返回新tag
13
+ if (usingComponents.includes(newTag)) return newTag
14
+ return tag
15
+ }
16
+ }
17
+ }
@@ -39,6 +39,7 @@ const view = require('./view')
39
39
  const webView = require('./web-view')
40
40
  const wxs = require('./wxs')
41
41
  const component = require('./component')
42
+ const fixHTMLTag = require('./fix-html-tag')
42
43
 
43
44
  module.exports = function getComponentConfigs ({ warn, error }) {
44
45
  /**
@@ -79,6 +80,7 @@ module.exports = function getComponentConfigs ({ warn, error }) {
79
80
 
80
81
  // 转换规则只需以微信为基准配置微信和支付宝的差异部分,比如微信和支付宝都支持但是写法不一致,或者微信支持而支付宝不支持的部分(抛出错误或警告)
81
82
  return [
83
+ fixHTMLTag(),
82
84
  ...Nonsupport({ print }),
83
85
  ad({ print }),
84
86
  view({ print }),
@@ -1,3 +1,12 @@
1
+ const {
2
+ isRichTextTag,
3
+ isUnaryTag,
4
+ isSpace,
5
+ isContWidth,
6
+ isContHeight,
7
+ isContConRow
8
+ } = require('../../../utils/dom-tag-config')
9
+
1
10
  // eslint-disable-next-line
2
11
  const attribute = /^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/ // useless escape
3
12
  const ncname = '[a-zA-Z_][\\w\\-\\.]*'
@@ -11,36 +20,6 @@ const comment = /^<!\--/
11
20
  const invalidAttributeRE = /[\s"'<>\/=]/
12
21
  let currentParent
13
22
 
14
- function makeMap (str, expectsLowerCase) {
15
- const map = Object.create(null)
16
- const list = str.split(',')
17
- for (let i = 0; i < list.length; i++) {
18
- map[list[i]] = true
19
- }
20
- return expectsLowerCase
21
- ? val => map[val.toLowerCase()]
22
- : val => map[val]
23
- }
24
-
25
- const isRichTextTag = makeMap(
26
- 'a,abbr,address,article,aside,b,bdi,bdo,big,blockquote,br,caption,' +
27
- 'center,cite,code,col,colgroup,dd,del,div,dl,dt,em,fieldset,' +
28
- 'font,footer,h1,h2,h3,h4,h5,h6,header,hr,i,img,ins,label,legend,' +
29
- 'li,mark,nav,ol,p,pre,q,rt,ruby,s,section,small,span,strong,sub,sup,' +
30
- 'table,tbody,td,tfoot,th,thead,tr,tt,u,ul'
31
- )
32
- const isUnaryTag = makeMap(
33
- 'area,base,br,col,embed,frame,hr,img,input,isindex,keygen,' +
34
- 'link,meta,param,source,track,wbr'
35
- )
36
- const isSpace = makeMap('ensp,emsp,nbsp')
37
-
38
- const isContWidth = makeMap('col,colgroup,img,table,td,th,tr')
39
-
40
- const isContHeight = makeMap('img,td,th,tr')
41
-
42
- const isContConRow = makeMap('td,th,tr')
43
-
44
23
  function makeAttrsMap (attrs) {
45
24
  const map = {}
46
25
  for (let i = 0, l = attrs.length; i < l; i++) {
@@ -144,20 +144,8 @@ export function inheritEvent (type, oe, detail = {}) {
144
144
  }
145
145
 
146
146
  export function getCustomEvent (type, detail = {}, target = null) {
147
- const targetInfo = {}
148
- if (target) {
149
- const targetEl = target.$el || {}
150
- const info = {
151
- id: targetEl.id || '',
152
- dataset: targetEl.dataset || {},
153
- offsetTop: targetEl.offsetTop || 0,
154
- offsetLeft: targetEl.offsetLeft || 0
155
- }
156
- Object.assign(targetInfo, {
157
- target: info,
158
- currentTarget: info
159
- })
160
- }
147
+ const targetEl = (target && target.$el) || null
148
+ const targetInfo = targetEl ? { target: targetEl, currentTarget: targetEl } : {}
161
149
  return {
162
150
  type,
163
151
  detail,
@@ -1,13 +1,13 @@
1
1
  <template>
2
- <div class="mpx-movable-scroll-content" ref="scrollContent">
3
- <div class="mpx-movable-scroll-item">
4
- <slot></slot>
5
- </div>
2
+ <div class="mpx-movable-scroll-content" ref="scrollContent">
3
+ <div class="mpx-movable-scroll-item">
4
+ <slot></slot>
6
5
  </div>
6
+ </div>
7
7
  </template>
8
8
 
9
9
  <script type="text/ecmascript-6">
10
- import {getCustomEvent} from './getInnerListeners'
10
+ import {getCustomEvent, extendEvent} from './getInnerListeners'
11
11
  import BScroll from '@better-scroll/core'
12
12
  import Movable from '@better-scroll/movable'
13
13
  import Zoom from '@better-scroll/zoom'
@@ -121,6 +121,13 @@
121
121
  newVal = 0.5
122
122
  }
123
123
  this.bs.zoomTo(newVal, 'center', 'center')
124
+ },
125
+ disabled (newVal) {
126
+ if (newVal) {
127
+ this.bs && this.bs.disable()
128
+ } else {
129
+ this.bs && this.bs.enable()
130
+ }
124
131
  }
125
132
  },
126
133
  mounted () {
@@ -204,6 +211,14 @@
204
211
  this.bs.movingDirectionY = -1
205
212
  }
206
213
  })
214
+ actionsHandlerHooks.on('start', (e) => {
215
+ extendEvent(e, { detail: Object.assign({}, e.detail) })
216
+ this.$emit('touchstart', e)
217
+ })
218
+ actionsHandlerHooks.on('end', (e) => {
219
+ extendEvent(e, { detail: Object.assign({}, e.detail) })
220
+ this.$emit('touchend', e)
221
+ })
207
222
  actionsHandlerHooks.on('move', ({ deltaX, deltaY, e }) => {
208
223
  if (this.isZooming) {
209
224
  return
@@ -215,7 +230,9 @@
215
230
  this.touchEvent = 'vtouchmove'
216
231
  }
217
232
  }
218
- this.$emit(this.touchEvent, getCustomEvent(this.touchEvent, {}, this))
233
+ extendEvent(e, { detail: Object.assign({}, e.detail), currentTarget: e.target })
234
+ this.$emit(this.touchEvent, e)
235
+ this.$emit('touchmove', e)
219
236
  this.isFirstTouch = false
220
237
  })
221
238
  if (this.inertia) { // movable-view是否带有惯性
@@ -302,7 +319,9 @@
302
319
  }
303
320
  </script>
304
321
  <style lang="stylus" rel="stylesheet/stylus" scoped>
305
- .mpx-movable-scroll-content {
306
- position: absolute
307
- }
322
+ .mpx-movable-scroll-content
323
+ position: absolute
324
+ .mpx-movable-scroll-item
325
+ width: 100%
326
+ height: 100%
308
327
  </style>
@@ -163,7 +163,7 @@
163
163
  height: 100%
164
164
  overflow: hidden
165
165
  text-align: center
166
- font-size: 14px
166
+ font-size: 16px
167
167
  position: relative
168
168
 
169
169
  &.mpx-picker-fade-enter, &.mpx-picker-fade-leave-active
@@ -264,10 +264,9 @@
264
264
  },
265
265
  initLayerComputed () {
266
266
  const wrapper = this.$refs.wrapper
267
- const wrapperWidth = wrapper.offsetWidth
268
- const wrapperHeight = wrapper.offsetHeight
269
- this.$refs.innerWrapper.style.width = `${wrapperWidth}px`
270
- this.$refs.innerWrapper.style.height = `${wrapperHeight}px`
267
+ const computedStyle = getComputedStyle(wrapper)
268
+ this.$refs.innerWrapper.style.width = `${computedStyle.clientWidth - parseInt(computedStyle.paddingLeft) - parseInt(computedStyle.paddingRight)}px`
269
+ this.$refs.innerWrapper.style.height = `${computedStyle.clientHeight - parseInt(computedStyle.paddingTop) - parseInt(computedStyle.paddingBottom)}px`
271
270
  const innerWrapper = this.$refs.innerWrapper
272
271
  const childrenArr = Array.from(innerWrapper.children)
273
272
 
@@ -146,6 +146,11 @@
146
146
  classList: ''
147
147
  }
148
148
  },
149
+ watch: {
150
+ muted (val) {
151
+ this.mutedCopy = val
152
+ }
153
+ },
149
154
  mounted () {
150
155
  this.initStyle()
151
156
  this.initEvent()
@@ -0,0 +1,27 @@
1
+ <template>
2
+ <view>局部构建兜底页面</view>
3
+ <view>当前路由:{{currentRoute}}</view>
4
+ </template>
5
+
6
+ <script>
7
+ import { onLoad } from '@mpxjs/core'
8
+ import { createPage } from '@mpxjs/core'
9
+
10
+ createPage({
11
+ data() {
12
+ return {
13
+ currentRoute: '',
14
+ }
15
+ },
16
+ onLoad() {
17
+ this.getPagePath()
18
+ },
19
+ methods: {
20
+ getPagePath() {
21
+ const pages = getCurrentPages() || []
22
+ const currPage = pages[pages.length - 1]
23
+ this.currentRoute = currPage && currPage.route || ''
24
+ },
25
+ }
26
+ })
27
+ </script>
@@ -19,9 +19,159 @@ dangerousKeys.split(',').forEach((key) => {
19
19
  dangerousKeyMap[key] = true
20
20
  })
21
21
 
22
+ // 判断 Identifier 是否需要处理
23
+ function checkBindThis (path) {
24
+ return !(t.isDeclaration(path.parent) && path.parentKey === 'id') &&
25
+ !(t.isFunction(path.parent) && path.listKey === 'params') &&
26
+ !(t.isMethod(path.parent) && path.parentKey === 'key' && !path.parent.computed) &&
27
+ !(t.isProperty(path.parent) && path.parentKey === 'key' && !path.parent.computed) &&
28
+ !(t.isMemberExpression(path.parent) && path.parentKey === 'property' && !path.parent.computed) &&
29
+ !t.isArrayPattern(path.parent) &&
30
+ !t.isObjectPattern(path.parent) &&
31
+ !hash[path.node.name]
32
+ }
33
+
34
+ // 计算访问路径
35
+ function calPropName (path) {
36
+ let current = path.parentPath
37
+ let last = path
38
+ let keyPath = '' + path.node.name
39
+
40
+ while (current.isMemberExpression() && last.parentKey !== 'property') {
41
+ if (current.node.computed) {
42
+ if (t.isLiteral(current.node.property)) {
43
+ if (t.isStringLiteral(current.node.property)) {
44
+ if (dangerousKeyMap[current.node.property.value]) {
45
+ break
46
+ }
47
+ keyPath += `.${current.node.property.value}`
48
+ } else {
49
+ keyPath += `[${current.node.property.value}]`
50
+ }
51
+ } else {
52
+ break
53
+ }
54
+ } else {
55
+ if (dangerousKeyMap[current.node.property.name]) {
56
+ break
57
+ }
58
+ keyPath += `.${current.node.property.name}`
59
+ }
60
+ last = current
61
+ current = current.parentPath
62
+ }
63
+
64
+ return {
65
+ last,
66
+ keyPath
67
+ }
68
+ }
69
+
70
+ function checkDelAndGetPath (path) {
71
+ let current = path
72
+ let delPath = path
73
+ let canDel = true
74
+ let ignore = false
75
+ let replace = false
76
+
77
+ // 确定删除路径
78
+ while (!t.isBlockStatement(current)) {
79
+ // case: !!a
80
+ if (t.isUnaryExpression(current.parent) && current.key === 'argument') {
81
+ delPath = current.parentPath
82
+ } else if (t.isCallExpression(current.parent)) {
83
+ // case: String(a) || this._p(a)
84
+ const args = current.node.arguments || current.parent.arguments || []
85
+ if (args.length === 1) {
86
+ delPath = current.parentPath
87
+ } else {
88
+ // case: this._i(a, function() {})
89
+ canDel = false
90
+ break
91
+ }
92
+ } else if (t.isMemberExpression(current.parent)) { // case: String(a,'123').b.c
93
+ if (current.parent.computed && !t.isLiteral(current.parent.property)) { // case: a[b] or a.b[c.d]
94
+ canDel = false
95
+ break
96
+ } else {
97
+ delPath = current.parentPath
98
+ }
99
+ } else {
100
+ break
101
+ }
102
+
103
+ current = current.parentPath
104
+ }
105
+
106
+ // 确定是否可删除
107
+ while (!t.isBlockStatement(current) && canDel) {
108
+ const { key, container } = current
109
+ if (
110
+ t.isLogicalExpression(container) || // a && b
111
+ (t.isIfStatement(container) && key === 'test') // if (a) {}
112
+ ) {
113
+ canDel = false
114
+ break
115
+ }
116
+
117
+ if (t.isConditionalExpression(container)) {
118
+ if (key === 'test') canDel = false
119
+ else ignore = true
120
+ break
121
+ }
122
+
123
+ if (
124
+ t.isBinaryExpression(container) || // 运算 a + b
125
+ (key === 'value' && t.isObjectProperty(container) && canDel) // ({ name: a })
126
+ ) {
127
+ canDel = true
128
+ replace = true
129
+ // 不能break,case: if (a + b) {}
130
+ }
131
+
132
+ current = current.parentPath
133
+ }
134
+
135
+ return {
136
+ delPath,
137
+ canDel,
138
+ ignore,
139
+ replace
140
+ }
141
+ }
142
+
143
+ // 判断前缀是否存在(只判断前缀,全等的情况,会返回false)
144
+ function checkPrefix (keys, key) {
145
+ for (let i = 0; i < keys.length; i++) {
146
+ const str = keys[i]
147
+ if (key === str) continue
148
+ // 确保判断当前标识是完整的单词
149
+ if (key.startsWith(str) && (key[str.length] === '.' || key[str.length] === '[')) return true
150
+ }
151
+ return false
152
+ }
153
+
154
+ function dealRemove (path, replace) {
155
+ while (path.key === 'expression' && t.isExpressionStatement(path.parentPath)) {
156
+ path = path.parentPath
157
+ }
158
+
159
+ try {
160
+ if (replace) {
161
+ path.replaceWith(t.stringLiteral(''))
162
+ } else {
163
+ t.validate(path, path.key, null)
164
+ path.remove()
165
+ }
166
+ } catch (e) {
167
+ console.error(e)
168
+ }
169
+ }
170
+
22
171
  module.exports = {
23
172
  transform (code, {
24
173
  needCollect = false,
174
+ renderReduce = false,
25
175
  ignoreMap = {}
26
176
  } = {}) {
27
177
  const ast = babylon.parse(code, {
@@ -30,10 +180,71 @@ module.exports = {
30
180
  ]
31
181
  })
32
182
 
183
+ let currentBlock = null
184
+ const bindingsMap = new Map()
185
+
33
186
  const propKeys = []
34
187
  let isProps = false
35
188
 
189
+ const collectVisitor = {
190
+ BlockStatement: {
191
+ enter (path) { // 收集作用域下所有变量(keyPath)
192
+ bindingsMap.set(path, {
193
+ parent: currentBlock,
194
+ bindings: {}
195
+ })
196
+ currentBlock = path
197
+ },
198
+ exit (path) {
199
+ currentBlock = bindingsMap.get(path).parent
200
+ }
201
+ },
202
+ Identifier (path) {
203
+ if (
204
+ checkBindThis(path) &&
205
+ !path.scope.hasBinding(path.node.name) &&
206
+ !ignoreMap[path.node.name]
207
+ ) {
208
+ const { last, keyPath } = calPropName(path)
209
+ path.needBind = true
210
+ if (needCollect) {
211
+ last.collectPath = t.stringLiteral(keyPath)
212
+ }
213
+
214
+ if (!renderReduce) return
215
+
216
+ const { delPath, canDel, ignore, replace } = checkDelAndGetPath(path)
217
+ if (ignore) return
218
+
219
+ delPath.delInfo = {
220
+ keyPath,
221
+ canDel,
222
+ replace
223
+ }
224
+
225
+ const { bindings } = bindingsMap.get(currentBlock)
226
+ const target = bindings[keyPath] || []
227
+ target.push({
228
+ path: delPath,
229
+ canDel
230
+ })
231
+ bindings[keyPath] = target
232
+ }
233
+ }
234
+ }
235
+
36
236
  const bindThisVisitor = {
237
+ BlockStatement: {
238
+ enter (path) {
239
+ const scope = bindingsMap.get(path)
240
+ const parentScope = bindingsMap.get(scope.parent)
241
+ scope.pBindings = parentScope ? Object.assign({}, parentScope.bindings, parentScope.pBindings) : {}
242
+ currentBlock = path
243
+ },
244
+ exit (path) {
245
+ currentBlock = bindingsMap.get(path).parent
246
+ }
247
+ },
37
248
  // 标记收集props数据
38
249
  CallExpression: {
39
250
  enter (path) {
@@ -50,76 +261,65 @@ module.exports = {
50
261
  exit (path) {
51
262
  if (path.isProps) {
52
263
  // 移除无意义的__props调用
53
- path.replaceWith(path.node.arguments[0])
264
+ const args = path.node.arguments[0]
265
+ path.replaceWith(args)
54
266
  isProps = false
55
267
  delete path.isProps
56
268
  }
57
269
  }
58
270
  },
59
- Identifier (path) {
60
- if (
61
- !(t.isDeclaration(path.parent) && path.parentKey === 'id') &&
62
- !(t.isFunction(path.parent) && path.listKey === 'params') &&
63
- !(t.isMethod(path.parent) && path.parentKey === 'key' && !path.parent.computed) &&
64
- !(t.isProperty(path.parent) && path.parentKey === 'key' && !path.parent.computed) &&
65
- !(t.isMemberExpression(path.parent) && path.parentKey === 'property' && !path.parent.computed) &&
66
- !t.isArrayPattern(path.parent) &&
67
- !t.isObjectPattern(path.parent) &&
68
- !hash[path.node.name]
69
- ) {
70
- let current
71
- let last
72
- if (!path.scope.hasBinding(path.node.name) && !ignoreMap[path.node.name]) {
73
- // bind this
74
- path.replaceWith(t.memberExpression(t.thisExpression(), path.node))
271
+ // enter 先于特定标识执行
272
+ enter (path) {
273
+ // 删除重复变量
274
+ if (path.delInfo) {
275
+ const { keyPath, canDel, replace } = path.delInfo
276
+ delete path.delInfo
75
277
 
76
- if (isProps) {
77
- propKeys.push(path.node.property.name)
78
- }
278
+ if (canDel) {
279
+ const data = bindingsMap.get(currentBlock)
280
+ const { bindings, pBindings } = data
281
+ const allBindings = Object.assign({}, pBindings, bindings)
79
282
 
80
- if (needCollect) {
81
- // 找到访问路径
82
- current = path.parentPath
83
- last = path
84
- let keyPath = '' + path.node.property.name
85
- while (current.isMemberExpression() && last.parentKey !== 'property') {
86
- if (current.node.computed) {
87
- if (t.isLiteral(current.node.property)) {
88
- if (t.isStringLiteral(current.node.property)) {
89
- if (dangerousKeyMap[current.node.property.value]) {
90
- break
91
- }
92
- keyPath += `.${current.node.property.value}`
93
- } else {
94
- keyPath += `[${current.node.property.value}]`
95
- }
96
- } else {
97
- break
98
- }
99
- } else {
100
- if (dangerousKeyMap[current.node.property.name]) {
101
- break
102
- }
103
- keyPath += `.${current.node.property.name}`
283
+ // 优先判断前缀,再判断全等
284
+ if (checkPrefix(Object.keys(allBindings), keyPath) || pBindings[keyPath]) {
285
+ dealRemove(path, replace)
286
+ return
287
+ } else {
288
+ const currentBlockVars = bindings[keyPath]
289
+ if (currentBlockVars.length > 1) {
290
+ const index = currentBlockVars.findIndex(item => !item.canDel)
291
+ if (index !== -1 || currentBlockVars[0].path !== path) { // 当前block中存在不可删除的变量 || 不是第一个可删除变量,即可删除该变量
292
+ dealRemove(path, replace)
293
+ return
104
294
  }
105
- last = current
106
- current = current.parentPath
107
295
  }
108
- last.collectPath = t.stringLiteral(keyPath)
109
296
  }
110
297
  }
111
298
  }
299
+
300
+ // bind this 将 a 转换成 this.a
301
+ if (path.needBind) {
302
+ const name = path.node.name
303
+ if (name) { // 确保path没有被删除 且 没有被替换成字符串
304
+ if (isProps) {
305
+ propKeys.push(name)
306
+ }
307
+ path.replaceWith(t.memberExpression(t.thisExpression(), path.node))
308
+ }
309
+ delete path.needBind
310
+ }
112
311
  },
113
312
  MemberExpression: {
114
313
  exit (path) {
115
314
  if (path.collectPath) {
116
- path.replaceWith(t.callExpression(t.memberExpression(t.thisExpression(), t.identifier('_c')), [path.collectPath, path.node]))
315
+ path.node && path.replaceWith(t.callExpression(t.memberExpression(t.thisExpression(), t.identifier('_c')), [path.collectPath, path.node]))
117
316
  delete path.collectPath
118
317
  }
119
318
  }
120
319
  }
121
320
  }
122
321
 
322
+ traverse(ast, collectVisitor)
123
323
  traverse(ast, bindThisVisitor)
124
324
 
125
325
  return {
@@ -10,40 +10,13 @@ const getRulesRunner = require('../platform/index')
10
10
  const addQuery = require('../utils/add-query')
11
11
  const transDynamicClassExpr = require('./trans-dynamic-class-expr')
12
12
  const dash2hump = require('../utils/hump-dash').dash2hump
13
-
14
- /**
15
- * Make a map and return a function for checking if a key
16
- * is in that map.
17
- */
18
- function makeMap (str, expectsLowerCase) {
19
- const map = Object.create(null)
20
- const list = str.split(',')
21
- for (let i = 0; i < list.length; i++) {
22
- map[list[i]] = true
23
- }
24
- return expectsLowerCase
25
- ? function (val) {
26
- return map[val.toLowerCase()]
27
- }
28
- : function (val) {
29
- return map[val]
30
- }
31
- }
13
+ const makeMap = require('../utils/make-map')
14
+ const { isNonPhrasingTag } = require('../utils/dom-tag-config')
32
15
 
33
16
  const no = function () {
34
17
  return false
35
18
  }
36
19
 
37
- // HTML5 tags https://html.spec.whatwg.org/multipage/indices.html#elements-3
38
- // Phrasing Content https://html.spec.whatwg.org/multipage/dom.html#phrasing-content
39
- const isNonPhrasingTag = makeMap(
40
- 'address,article,aside,base,blockquote,body,caption,col,colgroup,dd,' +
41
- 'details,dialog,div,dl,dt,fieldset,figcaption,figure,footer,form,' +
42
- 'h1,h2,h3,h4,h5,h6,head,header,hgroup,hr,html,legend,li,menuitem,meta,' +
43
- 'optgroup,option,param,rp,rt,source,style,summary,tbody,td,tfoot,th,thead,' +
44
- 'title,tr,track'
45
- )
46
-
47
20
  /*!
48
21
  * HTML Parser By John Resig (ejohn.org)
49
22
  * Modified by Juriy "kangax" Zaytsev
@@ -653,6 +626,9 @@ function parse (template, options) {
653
626
  srcMode,
654
627
  type: 'template',
655
628
  testKey: 'tag',
629
+ data: {
630
+ usingComponents: options.usingComponents
631
+ },
656
632
  warn: _warn,
657
633
  error: _error
658
634
  })
@@ -20,6 +20,7 @@ module.exports = function (raw) {
20
20
  const packageName = queryObj.packageRoot || mpx.currentPackageRoot || 'main'
21
21
  const componentsMap = mpx.componentsMap[packageName]
22
22
  const wxsContentMap = mpx.wxsContentMap
23
+ const renderOptimizeRules = mpx.renderOptimizeRules
23
24
  const usingComponents = queryObj.usingComponents || []
24
25
  const componentPlaceholder = queryObj.componentPlaceholder || []
25
26
  const hasComment = queryObj.hasComment
@@ -97,6 +98,7 @@ global.currentInject = {
97
98
  try {
98
99
  bindResult = bindThis(rawCode, {
99
100
  needCollect: true,
101
+ renderReduce: matchCondition(resourcePath, renderOptimizeRules),
100
102
  ignoreMap: meta.wxsModuleMap
101
103
  })
102
104
  } catch (e) {
@@ -0,0 +1,101 @@
1
+ // These tag configs are shared between compiler-dom and runtime-dom, so they
2
+ // must be extracted in shared to avoid creating a dependency between the two.
3
+ const makeMap = require('./make-map')
4
+
5
+ // https://developer.mozilla.org/en-US/docs/Web/HTML/Element
6
+ const HTML_TAGS =
7
+ 'html,body,base,head,link,meta,style,title,address,article,aside,footer,' +
8
+ 'header,hgroup,h1,h2,h3,h4,h5,h6,nav,section,div,dd,dl,dt,figcaption,' +
9
+ 'figure,picture,hr,img,li,main,ol,p,pre,ul,a,b,abbr,bdi,bdo,br,cite,code,' +
10
+ 'data,dfn,em,i,kbd,mark,q,rp,rt,ruby,s,samp,small,span,strong,sub,sup,' +
11
+ 'time,u,var,wbr,area,audio,map,track,video,embed,object,param,source,' +
12
+ 'canvas,script,noscript,del,ins,caption,col,colgroup,table,thead,tbody,td,' +
13
+ 'th,tr,button,datalist,fieldset,form,input,label,legend,meter,optgroup,' +
14
+ 'option,output,progress,select,textarea,details,dialog,menu,' +
15
+ 'summary,template,blockquote,iframe,tfoot'
16
+
17
+ // https://developer.mozilla.org/en-US/docs/Web/SVG/Element
18
+ const SVG_TAGS =
19
+ 'svg,animate,animateMotion,animateTransform,circle,clipPath,color-profile,' +
20
+ 'defs,desc,discard,ellipse,feBlend,feColorMatrix,feComponentTransfer,' +
21
+ 'feComposite,feConvolveMatrix,feDiffuseLighting,feDisplacementMap,' +
22
+ 'feDistantLight,feDropShadow,feFlood,feFuncA,feFuncB,feFuncG,feFuncR,' +
23
+ 'feGaussianBlur,feImage,feMerge,feMergeNode,feMorphology,feOffset,' +
24
+ 'fePointLight,feSpecularLighting,feSpotLight,feTile,feTurbulence,filter,' +
25
+ 'foreignObject,g,hatch,hatchpath,image,line,linearGradient,marker,mask,' +
26
+ 'mesh,meshgradient,meshpatch,meshrow,metadata,mpath,path,pattern,' +
27
+ 'polygon,polyline,radialGradient,rect,set,solidcolor,stop,switch,symbol,' +
28
+ 'text,textPath,title,tspan,unknown,use,view'
29
+
30
+ const VOID_TAGS =
31
+ 'area,base,br,col,embed,hr,img,input,link,meta,param,source,track,wbr'
32
+
33
+ // HTML5 tags https://html.spec.whatwg.org/multipage/indices.html#elements-3
34
+ // Phrasing Content https://html.spec.whatwg.org/multipage/dom.html#phrasing-content
35
+ const isNonPhrasingTag = makeMap(
36
+ 'address,article,aside,base,blockquote,body,caption,col,colgroup,dd,' +
37
+ 'details,dialog,div,dl,dt,fieldset,figcaption,figure,footer,form,' +
38
+ 'h1,h2,h3,h4,h5,h6,head,header,hgroup,hr,html,legend,li,menuitem,meta,' +
39
+ 'optgroup,option,param,rp,rt,source,style,summary,tbody,td,tfoot,th,thead,' +
40
+ 'title,tr,track'
41
+ )
42
+
43
+ const isRichTextTag = makeMap(
44
+ 'a,abbr,address,article,aside,b,bdi,bdo,big,blockquote,br,caption,' +
45
+ 'center,cite,code,col,colgroup,dd,del,div,dl,dt,em,fieldset,' +
46
+ 'font,footer,h1,h2,h3,h4,h5,h6,header,hr,i,img,ins,label,legend,' +
47
+ 'li,mark,nav,ol,p,pre,q,rt,ruby,s,section,small,span,strong,sub,sup,' +
48
+ 'table,tbody,td,tfoot,th,thead,tr,tt,u,ul'
49
+ )
50
+
51
+ const isUnaryTag = makeMap(
52
+ 'area,base,br,col,embed,frame,hr,img,input,isindex,keygen,' +
53
+ 'link,meta,param,source,track,wbr'
54
+ )
55
+
56
+ // https://developers.weixin.qq.com/miniprogram/dev/component/
57
+ // 以后可能在框架中原生支持这些标签,所以需要进行判断
58
+ const isNativeMiniTag = makeMap(
59
+ 'cover-image,cover-view,match-media,movable-area,movable-view,' +
60
+ 'page-container,root-portal,scroll-view,swiper,swiper-item,view,' +
61
+ 'icon,progress,rich-text,text,button,checkbox,checkbox-group,editor,' +
62
+ 'form,input,keyboard-accessory,label,picker,picker-view,' +
63
+ 'picker-view-column,radio,radio-group,slider,switch,textarea,' +
64
+ 'grid-view,list-view,share-element,snapshot,span,sticky-header,' +
65
+ 'sticky-section,functional-page-navigator,navigator,audio,camera,' +
66
+ 'channel-live,channel-video,image,live-player,live-pusher,video,' +
67
+ 'voip-room,map,canvas,web-view,ad,ad-custom,official-account,' +
68
+ 'open-data,native-component,aria-component,page-meta'
69
+ )
70
+
71
+ const isSpace = makeMap('ensp,emsp,nbsp')
72
+
73
+ const isContWidth = makeMap('col,colgroup,img,table,td,th,tr')
74
+
75
+ const isContHeight = makeMap('img,td,th,tr')
76
+
77
+ const isContConRow = makeMap('td,th,tr')
78
+
79
+ const isHTMLTag = makeMap(HTML_TAGS)
80
+
81
+ const isSVGTag = makeMap(SVG_TAGS)
82
+
83
+ const isVoidTag = makeMap(VOID_TAGS)
84
+
85
+ // 是否为原始tag,包括 html tag 和小程序原生 tag
86
+ const isOriginTag = (tag) => isHTMLTag(tag) || isSVGTag(tag) || isVoidTag(tag) || isNativeMiniTag(tag)
87
+
88
+ module.exports = {
89
+ isOriginTag,
90
+ isHTMLTag,
91
+ isSVGTag,
92
+ isVoidTag,
93
+ isNonPhrasingTag,
94
+ isRichTextTag,
95
+ isUnaryTag,
96
+ isSpace,
97
+ isContWidth,
98
+ isContHeight,
99
+ isNativeMiniTag,
100
+ isContConRow
101
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Make a map and return a function for checking if a key
3
+ * is in that map.
4
+ */
5
+ module.exports = function makeMap (str, expectsLowerCase) {
6
+ const map = Object.create(null)
7
+ const list = str.split(',')
8
+ for (let i = 0; i < list.length; i++) {
9
+ map[list[i]] = true
10
+ }
11
+ return expectsLowerCase ? val => !!map[val.toLowerCase()] : val => !!map[val]
12
+ }
@@ -23,8 +23,14 @@ function capitalToHyphen (v) {
23
23
  return ret
24
24
  }
25
25
 
26
+ // 删除空行
27
+ function trimBlankRow (str) {
28
+ return str.replace(/^\s*[\r\n]/gm, '')
29
+ }
30
+
26
31
  module.exports = {
27
32
  isCapital,
28
33
  isMustache,
29
- capitalToHyphen
34
+ capitalToHyphen,
35
+ trimBlankRow
30
36
  }
@@ -9,8 +9,10 @@ const parseComponent = require('../parser')
9
9
  const getJSONContent = require('../utils/get-json-content')
10
10
  const resolve = require('../utils/resolve')
11
11
  const createJSONHelper = require('../json-compiler/helper')
12
+ const getRulesRunner = require('../platform/index')
12
13
  const { RESOLVE_IGNORED_ERR } = require('../utils/const')
13
14
  const RecordResourceMapDependency = require('../dependencies/RecordResourceMapDependency')
15
+ const RecordGlobalComponentsDependency = require('../dependencies/RecordGlobalComponentsDependency')
14
16
 
15
17
  module.exports = function (json, {
16
18
  loaderContext,
@@ -26,6 +28,7 @@ module.exports = function (json, {
26
28
  const mpx = loaderContext.getMpx()
27
29
  const {
28
30
  mode,
31
+ srcMode,
29
32
  env,
30
33
  projectRoot
31
34
  } = mpx
@@ -75,12 +78,44 @@ module.exports = function (json, {
75
78
  })
76
79
  }
77
80
 
81
+ const { resourcePath } = parseRequest(loaderContext.resource)
82
+ const isApp = !(pagesMap[resourcePath] || componentsMap[resourcePath])
83
+
78
84
  if (!json) {
79
85
  return callback()
80
86
  }
81
87
  // 由于json需要提前读取在template处理中使用,src的场景已经在loader中处理了,此处无需考虑json.src的场景
82
88
  try {
83
89
  jsonObj = JSON5.parse(json.content)
90
+ // 处理runner
91
+ const rulesRunnerOptions = {
92
+ mode,
93
+ srcMode,
94
+ type: 'json',
95
+ waterfall: true,
96
+ warn: emitWarning,
97
+ error: emitError,
98
+ data: {
99
+ // polyfill global usingComponents & record globalComponents
100
+ globalComponents: mpx.usingComponents
101
+ }
102
+ }
103
+
104
+ if (!isApp) {
105
+ rulesRunnerOptions.mainKey = pagesMap[resourcePath] ? 'page' : 'component'
106
+ }
107
+
108
+ const rulesRunner = getRulesRunner(rulesRunnerOptions)
109
+
110
+ if (rulesRunner) {
111
+ rulesRunner(jsonObj)
112
+ }
113
+ if (isApp) {
114
+ // 收集全局组件
115
+ Object.assign(mpx.usingComponents, jsonObj.usingComponents)
116
+ // 在 rulesRunner 运行后保存全局注册组件
117
+ loaderContext._module.addPresentationalDependency(new RecordGlobalComponentsDependency(mpx.usingComponents, loaderContext.context))
118
+ }
84
119
  } catch (e) {
85
120
  return callback(e)
86
121
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mpxjs/webpack-plugin",
3
- "version": "2.8.48",
3
+ "version": "2.8.50",
4
4
  "description": "mpx compile core",
5
5
  "keywords": [
6
6
  "mpx"
@@ -29,7 +29,6 @@
29
29
  "@better-scroll/zoom": "^2.5.1",
30
30
  "acorn-walk": "^7.2.0",
31
31
  "async": "^2.6.0",
32
- "consolidate": "^0.15.1",
33
32
  "css": "^2.2.1",
34
33
  "css-selector-tokenizer": "^0.7.0",
35
34
  "cssnano": "^5.0.16",
@@ -82,5 +81,5 @@
82
81
  "engines": {
83
82
  "node": ">=14.14.0"
84
83
  },
85
- "gitHead": "4cbd364322aadc0e9727a0d852ca3ca1c8e0b1ca"
84
+ "gitHead": "32f30631cc5f37503fb7791cb3b0d6c901ee2b27"
86
85
  }
@@ -1,3 +0,0 @@
1
- <template>
2
- <view>局部构建兜底页面</view>
3
- </template>
@@ -1,29 +0,0 @@
1
- // loader for pre-processing templates with e.g. pug
2
-
3
- const cons = require('consolidate')
4
- const loaderUtils = require('loader-utils')
5
-
6
- module.exports = function (content) {
7
- this.cacheable && this.cacheable()
8
- const callback = this.async()
9
- const opt = loaderUtils.getOptions(this) || {}
10
-
11
- if (!cons[opt.engine]) {
12
- return callback(new Error(
13
- 'Template engine \'' + opt.engine + '\' ' +
14
- 'isn\'t available in Consolidate.js'
15
- ))
16
- }
17
-
18
- const templateOption = opt.templateOption
19
-
20
- // for relative includes
21
- templateOption.filename = this.resourcePath
22
-
23
- cons[opt.engine].render(content, templateOption, function (err, html) {
24
- if (err) {
25
- return callback(err)
26
- }
27
- callback(null, html)
28
- })
29
- }