diff --git a/build/rollup.config.wxs.js b/build/rollup.config.wxs.js new file mode 100644 index 0000000000000000000000000000000000000000..60b3a86aa327b2aa0bbc5a0f06a87804cc5ebe9f --- /dev/null +++ b/build/rollup.config.wxs.js @@ -0,0 +1,7 @@ +module.exports = { + input: 'src/core/runtime/mp/wxs.js', + output: { + file: 'packages/uni-mp-weixin/dist/wxs.js', + format: 'es' + } +} diff --git a/package.json b/package.json index bf3673027404117be89bd5ca3933590856a501c2..fd12771f9704061fa694be134751edfd24b0799b 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,8 @@ "build:mp-baidu": "cross-env UNI_PLATFORM=mp-baidu rollup -c build/rollup.config.mp.js", "build:mp-alipay": "cross-env UNI_PLATFORM=mp-alipay rollup -c build/rollup.config.mp.js", "build:mp-toutiao": "cross-env UNI_PLATFORM=mp-toutiao rollup -c build/rollup.config.mp.js", - "build:mp-weixin:mp": "npm run lint && cross-env UNI_PLATFORM=mp-weixin UNI_MP=true rollup -c build/rollup.config.mp.js", + "build:mp-weixin:mp": "npm run lint && cross-env UNI_PLATFORM=mp-weixin UNI_MP=true rollup -c build/rollup.config.mp.js", + "build:mp-weixin:wxs": "rollup -c build/rollup.config.wxs.js", "build:runtime": "npm run lint && npm run build:mp-weixin && npm run build:mp-qq && npm run build:mp-alipay && npm run build:mp-baidu && npm run build:mp-toutiao && npm run build:app-plus", "build:stat": "npm run lint && rollup -c build/rollup.config.stat.js", "build:web-view": "npm run lint && rollup -c build/rollup.config.web-view.js", diff --git a/packages/uni-app-plus/dist/index.v3.js b/packages/uni-app-plus/dist/index.v3.js index cdfcb2ae7c1500c0a32cc3207a30c3b9ca3bb11e..b8c45d62ab1ab454f9d20c6768322be94da69571 100644 --- a/packages/uni-app-plus/dist/index.v3.js +++ b/packages/uni-app-plus/dist/index.v3.js @@ -12099,7 +12099,9 @@ var serviceContext = (function () { Object.keys(dataset).forEach(name => { try { ret[name] = JSON.parse(dataset[name]); - } catch (e) {} + } catch (e) { // dataset 存在两种,一种是被JSON.stringify的,一种是原始的 + ret[name] = dataset[name]; + } }); return ret } diff --git a/packages/uni-cli-shared/__tests__/pages.spec.js b/packages/uni-cli-shared/__tests__/pages.spec.js new file mode 100644 index 0000000000000000000000000000000000000000..45a3786585f42dbc47ecc4458e9731fe6f488f63 --- /dev/null +++ b/packages/uni-cli-shared/__tests__/pages.spec.js @@ -0,0 +1,27 @@ +const { + generateUsingComponentsCode, + generateGlobalUsingComponentsCode +} = require('../lib/pages') +describe('shared:pages', () => { + it('generate usingComponents', () => { + expect(generateUsingComponentsCode()).toBe('') + expect(generateUsingComponentsCode({})).toBe('') + expect(generateUsingComponentsCode({ + 'van-button': '/wxcomponents/vant/button/index', + 'van-card': '../../wxcomponents/vant/card/index' + })).toBe( + `import VanButton from '@/wxcomponents/vant/button/index.vue';import VanCard from '../../wxcomponents/vant/card/index.vue';global['__wxVueOptions'] = {components:{'van-button':VanButton,'van-card':VanCard}};` + ) + }) + it('generate global usingComponents', () => { + expect(generateGlobalUsingComponentsCode()).toBe('') + expect(generateGlobalUsingComponentsCode({})).toBe('') + expect(generateGlobalUsingComponentsCode({ + 'van-button': '/wxcomponents/vant/button/index', + 'van-cell': 'wxcomponents/vant/cell/index', + 'van-cell-group': './wxcomponents/vant/cell-group/index' + })).toBe( + `import VanButton from '@/wxcomponents/vant/button/index.vue';import VanCell from './wxcomponents/vant/cell/index.vue';import VanCellGroup from './wxcomponents/vant/cell-group/index.vue';Vue.component('van-button',VanButton);Vue.component('van-cell',VanCell);Vue.component('van-cell-group',VanCellGroup);` + ) + }) +}) diff --git a/packages/uni-cli-shared/lib/json.js b/packages/uni-cli-shared/lib/json.js index d59ad3e1a9d4860b6f7216208cac41e4094ef89c..b1dbb558ef1f6236edc8ac034b90a2b0241cfa35 100644 --- a/packages/uni-cli-shared/lib/json.js +++ b/packages/uni-cli-shared/lib/json.js @@ -1,19 +1,18 @@ const fs = require('fs') const path = require('path') const stripJsonComments = require('strip-json-comments') -const preprocessor = require('@dcloudio/vue-cli-plugin-uni/packages/webpack-preprocess-loader/preprocess') -const { - jsPreprocessOptions -} = require('./platform') function parseJson (content, preprocess = false) { if (typeof content === 'string') { if (preprocess) { + const preprocessor = require('@dcloudio/vue-cli-plugin-uni/packages/webpack-preprocess-loader/preprocess') + const { + jsPreprocessOptions + } = require('./platform') content = preprocessor.preprocess(content, jsPreprocessOptions.context, { type: jsPreprocessOptions.type }) } - content = JSON.parse(stripJsonComments(content)) } diff --git a/packages/uni-cli-shared/lib/pages.js b/packages/uni-cli-shared/lib/pages.js index 1a25233e692ded8f3c3e1190ec4e880620583281..1bcb5f538cbb2c1e4fd5bf10df323ed4ed90ef77 100644 --- a/packages/uni-cli-shared/lib/pages.js +++ b/packages/uni-cli-shared/lib/pages.js @@ -3,7 +3,9 @@ const path = require('path') const { removeExt, - normalizePath + normalizePath, + camelize, + capitalize } = require('./util') const { @@ -244,6 +246,87 @@ function parseEntry (pagesJson) { } } +function parseUsingComponents (usingComponents = {}) { + const components = [] + Object.keys(usingComponents).forEach(name => { + const identifier = capitalize(camelize(name)) + let source = usingComponents[name] + if (source.indexOf('/') === 0) { // 绝对路径 + source = '@' + source + } else if (source.indexOf('.') !== 0) { // 相对路径 + source = './' + source + } + components.push({ + name, + identifier, + source + }) + }) + return components +} + +function generateUsingComponentsCode (usingComponents) { + const components = parseUsingComponents(usingComponents) + const importCode = [] + const componentsCode = [] + components.forEach(({ + name, + identifier, + source + }) => { + importCode.push(`import ${identifier} from '${source}.vue'`) + componentsCode.push(`'${name}':${identifier}`) + }) + if (!importCode.length) { + return '' + } + return `${importCode.join(';')};global['__wxVueOptions'] = {components:{${componentsCode.join(',')}}};` +} + +function generateGlobalUsingComponentsCode (usingComponents) { + const components = parseUsingComponents(usingComponents) + const importCode = [] + const componentsCode = [] + components.forEach(({ + name, + identifier, + source + }) => { + importCode.push(`import ${identifier} from '${source}.vue'`) + componentsCode.push(`Vue.component('${name}',${identifier})`) + }) + if (!importCode.length) { + return '' + } + return `${importCode.join(';')};${componentsCode.join(';')};` +} + +function getGlobalUsingComponentsCode () { + const pagesJson = getPagesJson() + const usingComponents = pagesJson.globalStyle && pagesJson.globalStyle.usingComponents + if (!usingComponents) { + return '' + } + return generateGlobalUsingComponentsCode(usingComponents) +} + +function getUsingComponentsCode (pagePath) { + const usingComponents = usingComponentsPages[pagePath] + if (!usingComponents) { + return '' + } + return generateUsingComponentsCode(usingComponents) +} + +const usingComponentsPages = Object.create(null) + +function addPageUsingComponents (pagePath, usingComponents) { + if (usingComponents && Object.keys(usingComponents).length) { + console.log(pagePath + ':' + JSON.stringify(usingComponents)) + usingComponentsPages[pagePath] = usingComponents + } +} + module.exports = { getMainEntry, getNVueMainEntry, @@ -251,5 +334,10 @@ module.exports = { parseEntry, getPagesJson, parsePagesJson, - pagesJsonJsFileName + pagesJsonJsFileName, + addPageUsingComponents, + getUsingComponentsCode, + generateUsingComponentsCode, + getGlobalUsingComponentsCode, + generateGlobalUsingComponentsCode } diff --git a/packages/uni-cli-shared/lib/util.js b/packages/uni-cli-shared/lib/util.js index 699c4c74c472134e0388544e6416bd48838d3016..e3a2f4d5e76a188ed8d45293bb9deb46b37113a2 100644 --- a/packages/uni-cli-shared/lib/util.js +++ b/packages/uni-cli-shared/lib/util.js @@ -48,7 +48,11 @@ const camelizeRE = /-(\w)/g const camelize = cached((str) => { return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : '') -}) +}) + +function capitalize (str) { + return str.charAt(0).toUpperCase() + str.slice(1) +} const hyphenateRE = /\B([A-Z])/g @@ -106,7 +110,8 @@ module.exports = { }, hashify, removeExt, - camelize, + camelize, + capitalize, hyphenate, normalizePath, convertStaticStyle, diff --git a/packages/uni-migration/__tests__/wxml.spec.js b/packages/uni-migration/__tests__/wxml.spec.js index ebf260d136753217b5731f5323c0a74f59e0c476..8c0ca8a47ea7d22c80e4d5970a911d2e9a247b25 100644 --- a/packages/uni-migration/__tests__/wxml.spec.js +++ b/packages/uni-migration/__tests__/wxml.spec.js @@ -9,37 +9,37 @@ describe('wxml:compiler', () => { it('generate event', () => { assertCodegen( ``, - `` + `` ) assertCodegen( ``, - `` + `` ) }) it('generate class', () => { assertCodegen( ``, - `` + `` ) }) it('generate v-if', () => { assertCodegen( '{{ item.name }}', - `{{ item.name }}` + `{{ item.name }}` ) }) it('generate v-for', () => { assertCodegen( '', - `` + `` ) assertCodegen( '', - `` + `` ) assertCodegen( '', - `` + `` ) }) it('generate root element', () => { @@ -51,7 +51,7 @@ describe('wxml:compiler', () => { assertCodegen( ` `, - `` + `` ) diff --git a/packages/uni-migration/lib/mp-weixin/index.js b/packages/uni-migration/lib/mp-weixin/index.js index 18cce709b2bf7469b0a00969e407a7853f2fc5bd..5392b5d2e146438961cbb97f7a8a5beb33161068 100644 --- a/packages/uni-migration/lib/mp-weixin/index.js +++ b/packages/uni-migration/lib/mp-weixin/index.js @@ -1,12 +1,8 @@ -const patch = require('./patch') module.exports = { options: { extname: { template: '.wxml', style: '.wxss' - }, - shouldWrapper(filepath) { - return patch.wrapper(filepath) } }, transform: require('./transform'), diff --git a/packages/uni-migration/lib/mp-weixin/patch.js b/packages/uni-migration/lib/mp-weixin/patch.js index bcd2ccfc01a0bc5cb00b48535fb21b715dd9bbeb..733ceed9dddf6573fe6707867069846407d11b37 100644 --- a/packages/uni-migration/lib/mp-weixin/patch.js +++ b/packages/uni-migration/lib/mp-weixin/patch.js @@ -65,26 +65,7 @@ function patchVue(file) { } } -const VANT_WRAPPERS = [ - function test(filepath) { - return filepath.indexOf('/cell/index') !== -1 - }, - function test(filepath) { - return filepath.indexOf('/sticky/index') !== -1 - } -] - -const PATCH_WRAPPERS = [ - ...VANT_WRAPPERS -] - -function patchWrapper(filepath) { - filepath = normalizePath(filepath) - return !!PATCH_WRAPPERS.find(test => test(filepath)) -} - module.exports = { vue: patchVue, - asset: patchAsset, - wrapper: patchWrapper + asset: patchAsset } diff --git a/packages/uni-migration/lib/mp-weixin/transform/template-transformer/transform/generate.js b/packages/uni-migration/lib/mp-weixin/transform/template-transformer/transform/generate.js index 8e9e402c5bb3ba425fc22fb44d340e8d046192f6..f7198b6b8226a1809d0897fb56e8b6a680c324a6 100644 --- a/packages/uni-migration/lib/mp-weixin/transform/template-transformer/transform/generate.js +++ b/packages/uni-migration/lib/mp-weixin/transform/template-transformer/transform/generate.js @@ -57,30 +57,6 @@ function genWxs(wxs, state) { return [wxsCode.join('').trim(), wxsFiles] } -function shouldWrapper(node, state) { - if (state.shouldWrapper(state.filepath)) { - return true - } - node.children = node.children.filter(child => { // remove \n - if (child.type === 'text' && !child.data.trim()) { - return false - } - return true - }) - if (node.children.length > 1) { // multi root - return true - } - const rootNode = node.children[0] - if (rootNode && rootNode.name === 'slot') { // slot root - return true - } - return false -} - module.exports = function generate(node, state) { - // [`${genChildren(node).trim()}`, ...genWxs(state.wxs, state)] - // if (shouldWrapper(node, state)) { - return [`${genChildren(node).trim()}`, ...genWxs(state.wxs, state)] - // } - // return [genChildren(node).trim(), ...genWxs(state.wxs, state)] + return [`${genChildren(node).trim()}`, ...genWxs(state.wxs, state)] } diff --git a/packages/uni-mp-weixin/dist/mp.js b/packages/uni-mp-weixin/dist/mp.js index 7abcd6c64af38bbb8421fb1b707217805e13f4ae..393ef8c107bf380126216a9fb7ace5cad1383c93 100644 --- a/packages/uni-mp-weixin/dist/mp.js +++ b/packages/uni-mp-weixin/dist/mp.js @@ -769,24 +769,6 @@ var polyfill = { } }; -/** - * wxs getRegExp - */ -function getRegExp () { - const args = Array.prototype.slice.call(arguments); - args.unshift(RegExp); - return new (Function.prototype.bind.apply(RegExp, args))() -} - -/** - * wxs getDate - */ -function getDate () { - const args = Array.prototype.slice.call(arguments); - args.unshift(Date); - return new (Function.prototype.bind.apply(Date, args))() -} - global['__wxRoute'] = ''; global['__wxComponents'] = Object.create(null); global['__wxVueOptions'] = Object.create(null); @@ -823,4 +805,4 @@ function Behavior (options) { const nextTick = Vue.nextTick; export default uni; -export { Behavior, Component, Page, getDate, getRegExp, nextTick }; +export { Behavior, Component, Page, nextTick }; diff --git a/packages/vue-cli-plugin-uni/lib/app-plus/index.js b/packages/vue-cli-plugin-uni/lib/app-plus/index.js index 293e9e7b0f24892a7d3e45670c1bbb5190fcf9ee..dfc36671ab4670dbd3f8eabfdbf12c0232424e11 100644 --- a/packages/vue-cli-plugin-uni/lib/app-plus/index.js +++ b/packages/vue-cli-plugin-uni/lib/app-plus/index.js @@ -7,6 +7,10 @@ const { getPlatformCompiler } = require('@dcloudio/uni-cli-shared') +const { + getGlobalUsingComponentsCode +} = require('@dcloudio/uni-cli-shared/lib/pages') + const { isUnaryTag, getPartialIdentifier @@ -17,17 +21,23 @@ const { // } = require('../cache-loader') const runtimePath = '@dcloudio/uni-mp-weixin/dist/mp.js' - -function getProvides () { - return { - '__f__': [path.resolve(__dirname, '../format-log.js'), 'default'], - 'wx': [runtimePath, 'default'], - 'wx.nextTick': [runtimePath, 'nextTick'], - 'Page': [runtimePath, 'Page'], - 'Component': [runtimePath, 'Component'], - 'Behavior': [runtimePath, 'Behavior'], - 'getDate': [runtimePath, 'getDate'], - 'getRegExp': [runtimePath, 'getRegExp'] +const wxsPath = '@dcloudio/uni-mp-weixin/dist/wxs.js' +function getProvides (isAppService) { + if (isAppService) { + return { // app-service + '__f__': [path.resolve(__dirname, '../format-log.js'), 'default'], + 'wx': [runtimePath, 'default'], + 'wx.nextTick': [runtimePath, 'nextTick'], + 'Page': [runtimePath, 'Page'], + 'Component': [runtimePath, 'Component'], + 'Behavior': [runtimePath, 'Behavior'], + 'getDate': [wxsPath, 'getDate'], + 'getRegExp': [wxsPath, 'getRegExp'] + } + } + return { // app-view + 'getDate': [wxsPath, 'getDate'], + 'getRegExp': [wxsPath, 'getRegExp'] } } @@ -66,15 +76,21 @@ const v3 = { const rules = [] + const scriptLoaders = [] if (isAppView) { - rules.push({ // 解析组件,css 等 - resourceQuery: /vue&type=script/, - use: [{ - loader: path.resolve(__dirname, - '../../packages/webpack-uni-app-loader/view/script') - }] + scriptLoaders.push({ + loader: path.resolve(__dirname, + '../../packages/webpack-uni-app-loader/view/script') }) } + scriptLoaders.push({ + loader: path.resolve(__dirname, + '../../packages/webpack-uni-app-loader/using-components') + }) + rules.push({ // 解析组件,css 等 + resourceQuery: /vue&type=script/, + use: scriptLoaders + }) // TODO 临时方案,将 wxs 也编译至 service rules.push({ resourceQuery: [/lang=wxs/, /blockType=wxs/], @@ -124,7 +140,7 @@ const v3 = { options: { compiler: getPlatformCompiler(), before: [ - beforeCode + statCode + beforeCode + statCode + getGlobalUsingComponentsCode() ] } }] @@ -146,7 +162,7 @@ const v3 = { ] }, plugins: [ - new webpack.ProvidePlugin(getProvides()) + new webpack.ProvidePlugin(getProvides(isAppService)) ] } }, diff --git a/packages/vue-cli-plugin-uni/lib/h5/index.js b/packages/vue-cli-plugin-uni/lib/h5/index.js index 7e566a8ecb50012f28b7828acc55c43714234f2f..36e498752d9ce2df0ade498a37668e5d4e7495d9 100644 --- a/packages/vue-cli-plugin-uni/lib/h5/index.js +++ b/packages/vue-cli-plugin-uni/lib/h5/index.js @@ -1,12 +1,16 @@ const fs = require('fs') const path = require('path') -const webpack = require('webpack') +const webpack = require('webpack') const { getMainEntry, getH5Options } = require('@dcloudio/uni-cli-shared') +const { + getGlobalUsingComponentsCode +} = require('@dcloudio/uni-cli-shared/lib/pages') + const modifyVueLoader = require('../vue-loader') const WebpackHtmlAppendPlugin = require('../../packages/webpack-html-append-plugin') @@ -23,14 +27,14 @@ const { } = getH5Options() const runtimePath = '@dcloudio/uni-mp-weixin/dist/mp.js' - +const wxsPath = '@dcloudio/uni-mp-weixin/dist/wxs.js' function getProvides () { return { 'Page': [runtimePath, 'Page'], 'Component': [runtimePath, 'Component'], 'Behavior': [runtimePath, 'Behavior'], - 'getDate': [runtimePath, 'getDate'], - 'getRegExp': [runtimePath, 'getRegExp'] + 'getDate': [wxsPath, 'getDate'], + 'getRegExp': [wxsPath, 'getRegExp'] } } @@ -105,7 +109,7 @@ module.exports = { loader: 'wrap-loader', options: { before: [ - beforeCode + statCode + beforeCode + statCode + getGlobalUsingComponentsCode() ] } }] diff --git a/packages/vue-cli-plugin-uni/packages/webpack-uni-app-loader/using-components.js b/packages/vue-cli-plugin-uni/packages/webpack-uni-app-loader/using-components.js new file mode 100644 index 0000000000000000000000000000000000000000..acae44f12ddb5653702d49cce2990bca5fcd03b1 --- /dev/null +++ b/packages/vue-cli-plugin-uni/packages/webpack-uni-app-loader/using-components.js @@ -0,0 +1,18 @@ +const path = require('path') + +const { + removeExt, + normalizePath +} = require('@dcloudio/uni-cli-shared') +const { + getUsingComponentsCode +} = require('@dcloudio/uni-cli-shared/lib/pages') + +module.exports = function(content, map) { + this.cacheable && this.cacheable() + const resourcePath = removeExt( + normalizePath(path.relative(process.env.UNI_INPUT_DIR, this.resourcePath)) + ) + console.log('resourcePath:' + resourcePath) + return getUsingComponentsCode(resourcePath) + content +} diff --git a/packages/vue-cli-plugin-uni/packages/webpack-uni-app-loader/view/main.js b/packages/vue-cli-plugin-uni/packages/webpack-uni-app-loader/view/main.js index f1c6eeb002e6025fe6e1502ebcde9f4b807e9433..cafd7f5b7a23353d1dad08f7a0ce334fe9927686 100644 --- a/packages/vue-cli-plugin-uni/packages/webpack-uni-app-loader/view/main.js +++ b/packages/vue-cli-plugin-uni/packages/webpack-uni-app-loader/view/main.js @@ -9,6 +9,10 @@ const { paths: [require.resolve('vue-loader')] })) // 确保使用的与 vue-loader 一致 +const { + getGlobalUsingComponentsCode +} = require('@dcloudio/uni-cli-shared/lib/pages') + const traverse = require('@dcloudio/webpack-uni-mp-loader/lib/babel/global-component-traverse') const genStylesCode = require('../../vue-loader/lib/codegen/styleInjection') @@ -92,6 +96,9 @@ function getStylesCode(loaderContext) { } module.exports = function(source, map) { + // 追加小程序全局自定义组件(仅v3) + source = getGlobalUsingComponentsCode() + source + return ` import 'uni-pages?${JSON.stringify({type:'view'})}' function initView(){ diff --git a/packages/webpack-uni-pages-loader/lib/platforms/app-plus/index.js b/packages/webpack-uni-pages-loader/lib/platforms/app-plus/index.js index 372f81ff240de8dcf5c637a3ff37f095273abdba..53e2d7ccbc7f167031f17030a12d9d9b25de2f5e 100644 --- a/packages/webpack-uni-pages-loader/lib/platforms/app-plus/index.js +++ b/packages/webpack-uni-pages-loader/lib/platforms/app-plus/index.js @@ -9,6 +9,10 @@ const { getFlexDirection } = require('@dcloudio/uni-cli-shared') +const { + addPageUsingComponents +} = require('@dcloudio/uni-cli-shared/lib/pages') + const { parseStyle } = require('../../util') @@ -476,6 +480,8 @@ module.exports = function (pagesJson, userManifestJson) { appJson.page = Object.create(null) const addPage = function (pagePath, windowOptions, nvue) { + // 缓存页面级usingComponents + addPageUsingComponents(pagePath, windowOptions.usingComponents) delete windowOptions.usingComponents appJson.page[pagePath] = { window: windowOptions, @@ -514,4 +520,4 @@ module.exports = function (pagesJson, userManifestJson) { return [manifest, definePages(appJson), appConfigService(appJson)] } return [app, manifest] -} +} diff --git a/src/core/runtime/mp/index.js b/src/core/runtime/mp/index.js index 6a3943d28d83335539c94a2ff0c22705ba963dbf..cfb342ccd169a95f7ae6239bd47fd28f087618e2 100644 --- a/src/core/runtime/mp/index.js +++ b/src/core/runtime/mp/index.js @@ -14,8 +14,6 @@ import { import polyfill from './polyfill/index' -export * from './wxs' - global['__wxRoute'] = '' global['__wxComponents'] = Object.create(null) global['__wxVueOptions'] = Object.create(null)