diff --git a/package.json b/package.json index fd12771f9704061fa694be134751edfd24b0799b..0904f2034303cf11185de9337bb9f9876d04ffc1 100644 --- a/package.json +++ b/package.json @@ -75,9 +75,9 @@ "rollup-plugin-uglify": "^6.0.3", "shell-exec": "^1.0.2", "strip-json-comments": "^2.0.1", - "vue": "^2.6.8", + "vue": "^2.6.11", "vue-router": "^3.0.1", - "vue-template-compiler": "^2.6.8", + "vue-template-compiler": "^2.6.11", "webpack": "^4.18.0", "webpack-bundle-analyzer": "^3.0.3", "webpack-virtual-modules": "^0.1.10" diff --git a/packages/uni-cli-shared/lib/pages.js b/packages/uni-cli-shared/lib/pages.js index 240734c6b55654b6d94c120ac41be390daa7ee1e..181a4e7a4f83d309a1e790aac4c835c48a7fb84c 100644 --- a/packages/uni-cli-shared/lib/pages.js +++ b/packages/uni-cli-shared/lib/pages.js @@ -308,7 +308,7 @@ function getGlobalUsingComponentsCode () { return '' } return generateGlobalUsingComponentsCode(usingComponents) -} +} function getUsingComponentsCode (pagePath) { const usingComponents = usingComponentsPages[pagePath] @@ -325,6 +325,35 @@ function addPageUsingComponents (pagePath, usingComponents) { usingComponentsPages[pagePath] = usingComponents } } +// 存储自动组件 +const autoComponentMap = {} + +function addAutoComponent (name) { + const options = process.UNI_AUTO_COMPONENTS + const opt = options.find(opt => opt.test(name)) + if (!opt) { // 不匹配 + return (autoComponentMap[name] = true) // cache + } + return (autoComponentMap[name] = { + name, + identifier: capitalize(camelize(name + '-auto-import')), + source: name.replace(opt.test, opt.replacement) + }) +} + +function getAutoComponents (autoComponents) { + const components = [] + autoComponents.forEach(name => { + let autoComponent = autoComponentMap[name] + if (!autoComponent) { + autoComponent = addAutoComponent(name) + } + if (autoComponent !== true) { + components.push(autoComponent) + } + }) + return components +} module.exports = { getMainEntry, @@ -334,7 +363,8 @@ module.exports = { getPagesJson, parsePagesJson, pagesJsonJsFileName, - addPageUsingComponents, + getAutoComponents, + addPageUsingComponents, getUsingComponentsCode, generateUsingComponentsCode, getGlobalUsingComponentsCode, diff --git a/packages/uni-template-compiler/__tests__/demo.js b/packages/uni-template-compiler/__tests__/demo.js index af51b9ee8ccbcda3e359529952c5be1b4d245004..58352526916c6470885b28ddad8e5702ef184a19 100644 --- a/packages/uni-template-compiler/__tests__/demo.js +++ b/packages/uni-template-compiler/__tests__/demo.js @@ -1,7 +1,12 @@ const compiler = require('../lib') const res = compiler.compile( ` - + + + + + + `, { miniprogram: true, resourcePath: '/User/fxy/Documents/test.wxml', @@ -14,9 +19,9 @@ const res = compiler.compile( mp: { platform: 'app-plus' }, - filterModules: ['swipe'], + filterModules: ['swipe'] // service: true, - view: true + // view: true }) console.log(require('util').inspect(res, { diff --git a/packages/uni-template-compiler/lib/auto-components.js b/packages/uni-template-compiler/lib/auto-components.js new file mode 100644 index 0000000000000000000000000000000000000000..bb6511847ad65460c58513fd2e341b03dc34acf3 --- /dev/null +++ b/packages/uni-template-compiler/lib/auto-components.js @@ -0,0 +1,12 @@ +const { + isComponent +} = require('./util') + +module.exports = { + preTransformNode (el, options) { + if (isComponent(el.tag)) { + // 挂在 isReservedTag 上边,可以保证外部访问到 + (options.isReservedTag.autoComponents || (options.isReservedTag.autoComponents = new Set())).add(el.tag) + } + } +} diff --git a/packages/uni-template-compiler/lib/index.js b/packages/uni-template-compiler/lib/index.js index 53a0310f5f51cc28c8d3196cbb7dbfa9dec991d5..876abd47056ed89c8dd506f71644cdb50d397a1a 100644 --- a/packages/uni-template-compiler/lib/index.js +++ b/packages/uni-template-compiler/lib/index.js @@ -26,8 +26,25 @@ const { isComponent } = require('./util') +function compileTemplate (source, options) { + const res = compile(source, options) + console.log(options) + const { + autoComponents + } = options.isReservedTag + if (autoComponents) { + console.log('检测到的自定义组件:' + [...autoComponents]) + } + res.components = `{ + 'uni-badge': require('@components/uni-badge/uni-badge.vue').default, + 'uni-tag': require('@components/uni-tag/uni-tag.vue').default + }` + return res +} + module.exports = { compile (source, options = {}) { + (options.modules || (options.modules = [])).push(require('./auto-components')) if (options.service) { (options.modules || (options.modules = [])).push(require('./app/service')) options.optimize = false // 启用 staticRenderFns @@ -37,7 +54,7 @@ module.exports = { options.getTagNamespace = () => false try { - return compile(source, options) + return compileTemplate(source, options) } catch (e) { console.error(source) throw e @@ -47,7 +64,7 @@ module.exports = { options.optimize = false // 暂不启用 staticRenderFns options.isReservedTag = (tagName) => false // 均为组件 try { - return compile(source, options) + return compileTemplate(source, options) } catch (e) { console.error(source) throw e @@ -55,7 +72,7 @@ module.exports = { } if (!options.mp) { // h5 - return compile(source, options) + return compileTemplate(source, options) } (options.modules || (options.modules = [])).push(compilerModule) @@ -64,7 +81,7 @@ module.exports = { options.modules.push(compilerAlipayModule) } - const res = compile(source, Object.assign(options, { + const res = compileTemplate(source, Object.assign(options, { optimize: false })) diff --git a/packages/uni-template-compiler/lib/util.js b/packages/uni-template-compiler/lib/util.js index bf119e07ee1ef92b62e11529ac089737c60b316f..ef479dd717d93c9118c033f48200d1b66577f585 100644 --- a/packages/uni-template-compiler/lib/util.js +++ b/packages/uni-template-compiler/lib/util.js @@ -6,9 +6,9 @@ const { METHOD_RENDER_LIST } = require('./constants') -function cached (fn) { +function cached(fn) { const cache = Object.create(null) - return function cachedFn (str) { + return function cachedFn(str) { const hit = cache[str] return hit || (cache[str] = fn(str)) } @@ -21,7 +21,7 @@ const camelize = cached((str) => { return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : '') }) -function getCode (node) { +function getCode(node) { return babelGenerate(t.cloneDeep(node), { compact: true, jsescOption: { @@ -31,11 +31,11 @@ function getCode (node) { }).code } -function traverseKey (ast, state) { +function traverseKey(ast, state) { let forKey = false babelTraverse(ast, { noScope: true, - ObjectProperty (path) { + ObjectProperty(path) { if (forKey) { return } @@ -44,7 +44,7 @@ function traverseKey (ast, state) { path.stop() } }, - CallExpression (path) { + CallExpression(path) { if (path.node.callee.name === METHOD_RENDER_LIST) { path.stop() } @@ -53,7 +53,7 @@ function traverseKey (ast, state) { return forKey } -function traverseFilter (ast, state) { +function traverseFilter(ast, state) { const filterModules = state.options.filterModules if (!filterModules.length) { return false @@ -61,7 +61,7 @@ function traverseFilter (ast, state) { let isFilter = false babelTraverse(ast, { noScope: true, - Identifier (path) { + Identifier(path) { if (filterModules.includes(path.node.name)) { const parentNode = path.parent if ( // t.msg || t['msg'] @@ -81,11 +81,11 @@ function traverseFilter (ast, state) { return isFilter } -function wrapper (code, reverse = false) { +function wrapper(code, reverse = false) { return reverse ? `{{!(${code})}}` : `{{${code}}}` } -function genCode (node, noWrapper = false, reverse = false, quotes = true) { +function genCode(node, noWrapper = false, reverse = false, quotes = true) { if (t.isStringLiteral(node)) { return reverse ? `!(${node.value})` : node.value } else if (t.isIdentifier(node)) { @@ -98,11 +98,11 @@ function genCode (node, noWrapper = false, reverse = false, quotes = true) { return noWrapper ? code : wrapper(code, reverse) } -function getForIndexIdentifier (id) { +function getForIndexIdentifier(id) { return `__i${id}__` } -function getForKey (forKey, forIndex, state) { +function getForKey(forKey, forIndex, state) { if (forKey) { if (t.isIdentifier(forKey)) { if (forIndex !== forKey.name) { // 非 forIndex @@ -121,7 +121,7 @@ function getForKey (forKey, forIndex, state) { return '' } -function processMemberProperty (node, state) { +function processMemberProperty(node, state) { if (node.computed) { const property = node.property if (t.isNumericLiteral(property)) { @@ -139,7 +139,7 @@ function processMemberProperty (node, state) { } } -function processMemberExpression (element, state) { +function processMemberExpression(element, state) { // item['order']=>item.order if (t.isMemberExpression(element)) { element = t.cloneDeep(element) @@ -152,19 +152,19 @@ function processMemberExpression (element, state) { babelTraverse(element, { noScope: true, - MemberExpression (path) { + MemberExpression(path) { processMemberProperty(path.node, state) } }) babelTraverse(element, { noScope: true, - MemberExpression (path) { + MemberExpression(path) { if (t.isStringLiteral(path.node.property)) { path.node.computed = false } }, - StringLiteral (path) { + StringLiteral(path) { path.replaceWith(t.identifier(path.node.value)) } }) @@ -172,7 +172,7 @@ function processMemberExpression (element, state) { return element } -function hasOwn (obj, key) { +function hasOwn(obj, key) { return hasOwnProperty.call(obj, key) } @@ -182,9 +182,10 @@ const { getTagName } = require('./h5') -function isComponent (tagName) { +function isComponent(tagName) { if ( tagName === 'block' || + tagName === 'component' || tagName === 'template' || tagName === 'keep-alive' ) { @@ -193,7 +194,21 @@ function isComponent (tagName) { return !hasOwn(tags, getTagName(tagName.replace('v-uni-', ''))) } +function makeMap(str, expectsLowerCase) { + const map = Object.create(null) + const list = str.split(',') + for (let i = 0; i < list.length; i++) { + map[list[i]] = true + } + return expectsLowerCase ? + val => map[val.toLowerCase()] : + val => map[val] +} module.exports = { + isUnaryTag: makeMap( + 'image,area,base,br,col,embed,frame,hr,img,input,isindex,keygen,' + + 'link,meta,param,source,track,wbr' + ), isComponent, genCode, getCode, diff --git a/packages/vue-cli-plugin-hbuilderx/build/vue-loader.conf.js b/packages/vue-cli-plugin-hbuilderx/build/vue-loader.conf.js index 38cee00a0d09aaeb52cab0ec126508e356e3d24c..2443bced74551b07181db7ba5b393a8f477bf5b5 100644 --- a/packages/vue-cli-plugin-hbuilderx/build/vue-loader.conf.js +++ b/packages/vue-cli-plugin-hbuilderx/build/vue-loader.conf.js @@ -1,4 +1,4 @@ -const TAGS = [ +const TAGS = [ 'ad', 'text', 'image', @@ -94,6 +94,7 @@ if (process.env.UNI_USING_NVUE_COMPILER) { module.exports = { preserveWhitespace: false, + isAppNVue: true, compiler: require('weex-template-compiler'), compilerOptions: { modules diff --git a/packages/vue-cli-plugin-hbuilderx/build/webpack.nvue.conf.js b/packages/vue-cli-plugin-hbuilderx/build/webpack.nvue.conf.js index cb5dc07cf363e0584355a0d99a7bdc61e01ad208..c45c8d3aff849c2fa4618d82732c0a8dae754f7e 100644 --- a/packages/vue-cli-plugin-hbuilderx/build/webpack.nvue.conf.js +++ b/packages/vue-cli-plugin-hbuilderx/build/webpack.nvue.conf.js @@ -1,7 +1,7 @@ const fs = require('fs') const path = require('path') const webpack = require('webpack') -const VueLoaderPlugin = require('vue-loader/lib/plugin') +const VueLoaderPlugin = require('@dcloudio/vue-cli-plugin-uni/packages/vue-loader/lib/plugin') const CopyWebpackPlugin = require('copy-webpack-plugin') const { @@ -36,21 +36,23 @@ const uniPath = process.env.UNI_USING_V8 ? '../packages/uni-app-plus-nvue-v8/dist/index.js' : '../packages/uni-app-plus-nvue/dist/index.js' -const provide = {} +const provide = {} -if (process.env.UNI_USING_V3 || process.env.UNI_USING_NATIVE) { - provide['uni.getCurrentSubNVue'] = [path.resolve(__dirname, '../packages/uni-app-plus-nvue/dist/get-current-sub-nvue.js'), 'default'] - provide['uni.requireNativePlugin'] = [path.resolve(__dirname, '../packages/uni-app-plus-nvue/dist/require-native-plugin.js'), 'default'] -} - -if (!process.env.UNI_USING_V3) { - if (!process.env.UNI_USING_NATIVE) { - provide['uni'] = [path.resolve(__dirname, uniPath), 'default'] - } - - if (process.env.UNI_USING_V8) { - provide['plus'] = [path.resolve(__dirname, uniPath), 'weexPlus'] - } +if (process.env.UNI_USING_V3 || process.env.UNI_USING_NATIVE) { + provide['uni.getCurrentSubNVue'] = [path.resolve(__dirname, + '../packages/uni-app-plus-nvue/dist/get-current-sub-nvue.js'), 'default'] + provide['uni.requireNativePlugin'] = [path.resolve(__dirname, + '../packages/uni-app-plus-nvue/dist/require-native-plugin.js'), 'default'] +} + +if (!process.env.UNI_USING_V3) { + if (!process.env.UNI_USING_NATIVE) { + provide['uni'] = [path.resolve(__dirname, uniPath), 'default'] + } + + if (process.env.UNI_USING_V8) { + provide['plus'] = [path.resolve(__dirname, uniPath), 'weexPlus'] + } } if ( @@ -110,17 +112,9 @@ const rules = [{ } }, { - test: /\.nvue(\?[^?]+)?$/, - use: [{ - loader: path.resolve(__dirname, '../packages/vue-loader'), - options: vueLoaderOptions - }], - exclude: excludeModuleReg -}, -{ - test: /\.vue(\?[^?]+)?$/, + test: [/\.nvue(\?[^?]+)?$/, /\.vue(\?[^?]+)?$/], use: [{ - loader: path.resolve(__dirname, '../packages/vue-loader'), + loader: require.resolve('@dcloudio/vue-cli-plugin-uni/packages/vue-loader'), options: vueLoaderOptions }], exclude: excludeModuleReg @@ -322,4 +316,4 @@ module.exports = function () { zlib: false } } -} +} diff --git a/packages/vue-cli-plugin-hbuilderx/module-alias.js b/packages/vue-cli-plugin-hbuilderx/module-alias.js index f29af64024cec273bda9ac5f9f09ac0eed9a25bb..a9147005d7f6f929777d578bbd2db2eae5b92f9e 100644 --- a/packages/vue-cli-plugin-hbuilderx/module-alias.js +++ b/packages/vue-cli-plugin-hbuilderx/module-alias.js @@ -9,16 +9,8 @@ const { // nvue override moduleAlias.addAlias('weex-styler', path.resolve(__dirname, 'packages/weex-styler')) moduleAlias.addAlias('weex-template-compiler', path.resolve(__dirname, 'packages/weex-template-compiler')) -moduleAlias.addAlias('./compileTemplate', path.resolve(__dirname, - 'packages/webpack-uni-nvue-loader/lib/compileTemplate')) -moduleAlias.addAlias('./codegen/styleInjection', path.resolve(__dirname, - 'packages/webpack-uni-nvue-loader/lib/styleInjection')) -moduleAlias.addAlias('./templateLoader', (fromPath, request, alias) => { - if (fromPath.indexOf('vue-loader') !== -1) { - return path.resolve(__dirname, 'packages/webpack-uni-nvue-loader/lib/templateLoader') - } - return request -}) +moduleAlias.addAlias('./compileTemplate', require.resolve( + '@dcloudio/vue-cli-plugin-uni/packages/@vue/component-compiler-utils/dist/compileTemplate')) if (isInHBuilderX) { moduleAlias.addAlias('typescript', path.resolve(process.env.UNI_HBUILDERX_PLUGINS, diff --git a/packages/vue-cli-plugin-hbuilderx/packages/vue-loader/index.js b/packages/vue-cli-plugin-hbuilderx/packages/vue-loader/index.js deleted file mode 100644 index 532d69ab932a5ad791c3b5461d61214465bf6834..0000000000000000000000000000000000000000 --- a/packages/vue-cli-plugin-hbuilderx/packages/vue-loader/index.js +++ /dev/null @@ -1,211 +0,0 @@ -const path = require('path') -const hash = require('hash-sum') -const qs = require('querystring') -const plugin = require('vue-loader/lib/plugin') -const selectBlock = require('vue-loader/lib/select') -const loaderUtils = require('loader-utils') -const { attrsToQuery } = require('vue-loader/lib/codegen/utils') -const { parse } = require('@vue/component-compiler-utils') -const genStylesCode = require('../webpack-uni-nvue-loader/lib/styleInjection') -const { genHotReloadCode } = require('vue-loader/lib/codegen/hotReload') -const genCustomBlocksCode = require('vue-loader/lib/codegen/customBlocks') -const componentNormalizerPath = require.resolve('vue-loader/lib/runtime/componentNormalizer') -const { NS } = require('vue-loader/lib/plugin') - -let errorEmitted = false - -function loadTemplateCompiler (loaderContext) { - try { - return require('vue-template-compiler') - } catch (e) { - if (/version mismatch/.test(e.toString())) { - loaderContext.emitError(e) - } else { - loaderContext.emitError(new Error( - `[vue-loader] vue-template-compiler must be installed as a peer dependency, ` + - `or a compatible compiler implementation must be passed via options.` - )) - } - } -} - -function hasRecyclable (template) { - return !!(template && template.attrs && template.attrs.recyclable) -} - -module.exports = function (source) { - const loaderContext = this - - if (!errorEmitted && !loaderContext['thread-loader'] && !loaderContext[NS]) { - loaderContext.emitError(new Error( - `vue-loader was used without the corresponding plugin. ` + - `Make sure to include VueLoaderPlugin in your webpack config.` - )) - errorEmitted = true - } - - const stringifyRequest = r => loaderUtils.stringifyRequest(loaderContext, r) - - const { - target, - request, - minimize, - sourceMap, - rootContext, - resourcePath, - resourceQuery - } = loaderContext - - const rawQuery = resourceQuery.slice(1) - const inheritQuery = `&${rawQuery}` - const incomingQuery = qs.parse(rawQuery) - const options = loaderUtils.getOptions(loaderContext) || {} - - const isServer = target === 'node' - const isShadow = !!options.shadowMode - const isProduction = options.productionMode || minimize || process.env.NODE_ENV === 'production' - const filename = path.basename(resourcePath) - const context = rootContext || process.cwd() - const sourceRoot = path.dirname(path.relative(context, resourcePath)) - - const descriptor = parse({ - source, - compiler: options.compiler || loadTemplateCompiler(loaderContext), - filename, - sourceRoot, - needMap: sourceMap - }) - - // if the query has a type field, this is a language block request - // e.g. foo.vue?type=template&id=xxxxx - // and we will return early - if (incomingQuery.type) { - return selectBlock( - descriptor, - loaderContext, - incomingQuery, - !!options.appendExtension - ) - } - - // module id for scoped CSS & hot-reload - const rawShortFilePath = path - .relative(context, resourcePath) - .replace(/^(\.\.[\/\\])+/, '') - - const shortFilePath = rawShortFilePath.replace(/\\/g, '/') + resourceQuery - - const id = hash( - isProduction - ? (shortFilePath + '\n' + source) - : shortFilePath - ) - - // feature information - const hasScoped = descriptor.styles.some(s => s.scoped) - const hasFunctional = descriptor.template && descriptor.template.attrs.functional - const needsHotReload = ( - !isServer && - !isProduction && - (descriptor.script || descriptor.template) && - options.hotReload !== false - ) - - // template - let templateImport = `var render, staticRenderFns` - let templateRequest - const recyclable = hasRecyclable(descriptor.template) // fixed by xxxxxx - if (descriptor.template) { - const src = descriptor.template.src || resourcePath - const idQuery = `&id=${id}` - const scopedQuery = hasScoped ? `&scoped=true` : `` - const attrsQuery = attrsToQuery(descriptor.template.attrs) - const query = `?vue&type=template${idQuery}${scopedQuery}${attrsQuery}${inheritQuery}` - const request = templateRequest = stringifyRequest(src + query) - if(recyclable){ // fixed by xxxxxx - templateImport = `import { render, staticRenderFns, recyclableRender } from ${request}` - } else { - templateImport = `import { render, staticRenderFns } from ${request}` - } - } - - // script - let scriptImport = `var script = {}` - if (descriptor.script) { - const src = descriptor.script.src || resourcePath - const attrsQuery = attrsToQuery(descriptor.script.attrs, 'js') - const query = `?vue&type=script${attrsQuery}${inheritQuery}` - const request = stringifyRequest(src + query) - scriptImport = ( - `import script from ${request}\n` + - `export * from ${request}` // support named exports - ) - } - - // styles - let stylesCode = `` - if (descriptor.styles.length) { - stylesCode = genStylesCode( - loaderContext, - descriptor.styles, - id, - resourcePath, - stringifyRequest, - needsHotReload, - isServer || isShadow // needs explicit injection? - ) - } - - let code = ` -${templateImport} -${scriptImport} -${stylesCode} - -/* normalize component */ -import normalizer from ${stringifyRequest(`!${componentNormalizerPath}`)} -var component = normalizer( - script, - render, - staticRenderFns, - ${hasFunctional ? `true` : `false`}, - ${`null`}, - ${hasScoped ? JSON.stringify(id) : `null`}, - ${isServer ? JSON.stringify(hash(request)) : `null`} - ${isShadow ? `,true` : ``} -) - `.trim() + `\n` - - if (descriptor.customBlocks && descriptor.customBlocks.length) { - code += genCustomBlocksCode( - descriptor.customBlocks, - resourcePath, - resourceQuery, - stringifyRequest - ) - } - - if (needsHotReload) { - code += `\n` + genHotReloadCode(id, hasFunctional, templateRequest) - } - if(/injectStyles/.test(stylesCode)){// fixed by xxxxxx - code +=`\ninjectStyles.call(component)` - } - // Expose filename. This is used by the devtools and Vue runtime warnings. - if (!isProduction) { - // Expose the file's full path in development, so that it can be opened - // from the devtools. - code += `\ncomponent.options.__file = ${JSON.stringify(rawShortFilePath.replace(/\\/g, '/'))}` - } else if (options.exposeFilename) { - // Libraies can opt-in to expose their components' filenames in production builds. - // For security reasons, only expose the file's basename in production. - code += `\ncomponent.options.__file = ${JSON.stringify(filename)}` - } - if(recyclable){ - code += `\nrecyclableRender && (component.options["@render"] = recyclableRender)` // fixed by xxxxxx - } - code += `\nexport default component.exports` - // console.log(code) - return code -} - -module.exports.VueLoaderPlugin = plugin diff --git a/packages/vue-cli-plugin-hbuilderx/packages/vue-loader/lib/loaders/pitcher.js b/packages/vue-cli-plugin-hbuilderx/packages/vue-loader/lib/loaders/pitcher.js deleted file mode 100644 index 6af379ba75109d3d97a5e53b8ee5650c1cac28c0..0000000000000000000000000000000000000000 --- a/packages/vue-cli-plugin-hbuilderx/packages/vue-loader/lib/loaders/pitcher.js +++ /dev/null @@ -1,160 +0,0 @@ -const qs = require('querystring') -const loaderUtils = require('loader-utils') -const hash = require('hash-sum') -const selfPath = require.resolve('vue-loader/lib/index') -const templateLoaderPath = require.resolve('vue-loader/lib/loaders/templateLoader') -const stylePostLoaderPath = require.resolve('vue-loader/lib/loaders/stylePostLoader') - -const isESLintLoader = l => /(\/|\\|@)eslint-loader/.test(l.path) -const isNullLoader = l => /(\/|\\|@)null-loader/.test(l.path) -const isCSSLoader = l => /(\/|\\|@)css-loader/.test(l.path) -const isCacheLoader = l => /(\/|\\|@)cache-loader/.test(l.path) -const isPitcher = l => l.path !== __filename -const isPreLoader = l => !l.pitchExecuted -const isPostLoader = l => l.pitchExecuted - -const dedupeESLintLoader = loaders => { - const res = [] - let seen = false - loaders.forEach(l => { - if (!isESLintLoader(l)) { - res.push(l) - } else if (!seen) { - seen = true - res.push(l) - } - }) - return res -} - -const shouldIgnoreCustomBlock = loaders => { - const actualLoaders = loaders.filter(loader => { - // vue-loader - if (loader.path === selfPath) { - return false - } - - // cache-loader - if (isCacheLoader(loader)) { - return false - } - - return true - }) - return actualLoaders.length === 0 -} - -module.exports = code => code - -// This pitching loader is responsible for intercepting all vue block requests -// and transform it into appropriate requests. -module.exports.pitch = function (remainingRequest) { - const options = loaderUtils.getOptions(this) - const { cacheDirectory, cacheIdentifier } = options - const query = qs.parse(this.resourceQuery.slice(1)) - - let loaders = this.loaders - - // if this is a language block request, eslint-loader may get matched - // multiple times - if (query.type) { - // if this is an inline block, since the whole file itself is being linted, - // remove eslint-loader to avoid duplicate linting. - if (/\.vue$/.test(this.resourcePath)) { - loaders = loaders.filter(l => !isESLintLoader(l)) - } else { - // This is a src import. Just make sure there's not more than 1 instance - // of eslint present. - loaders = dedupeESLintLoader(loaders) - } - } - - // remove self - loaders = loaders.filter(isPitcher) - - // do not inject if user uses null-loader to void the type (#1239) - if (loaders.some(isNullLoader)) { - return - } - - const genRequest = loaders => { - // Important: dedupe since both the original rule - // and the cloned rule would match a source import request. - // also make sure to dedupe based on loader path. - // assumes you'd probably never want to apply the same loader on the same - // file twice. - // Exception: in Vue CLI we do need two instances of postcss-loader - // for user config and inline minification. So we need to dedupe baesd on - // path AND query to be safe. - const seen = new Map() - const loaderStrings = [] - - loaders.forEach(loader => { - const identifier = typeof loader === 'string' - ? loader - : (loader.path + loader.query) - const request = typeof loader === 'string' ? loader : loader.request - if (!seen.has(identifier)) { - seen.set(identifier, true) - // loader.request contains both the resolved loader path and its options - // query (e.g. ??ref-0) - loaderStrings.push(request) - } - }) - - return loaderUtils.stringifyRequest(this, '-!' + [ - ...loaderStrings, - this.resourcePath + this.resourceQuery - ].join('!')) - } - - // Inject style-post-loader before css-loader for scoped CSS and trimming - if (query.type === `style`) { - const cssLoaderIndex = loaders.findIndex(isCSSLoader) - if (cssLoaderIndex > -1) { - const afterLoaders = loaders.slice(0, cssLoaderIndex + 1) - const beforeLoaders = loaders.slice(cssLoaderIndex + 1) - const request = genRequest([ - ...afterLoaders, - stylePostLoaderPath, - ...beforeLoaders - ]) - // console.log(request) - return `import mod from ${request}; export default mod; export * from ${request}` - } - } - - // for templates: inject the template compiler & optional cache - if (query.type === `template`) { - const path = require('path') - // fixed by xxxxxx - const cacheLoader = cacheDirectory && cacheIdentifier - ? [`${require.resolve('cache-loader')}??uni-cache-loader-template-options`] - : [] - - const preLoaders = loaders.filter(isPreLoader) - const postLoaders = loaders.filter(isPostLoader) - - const request = genRequest([ - ...cacheLoader, - ...postLoaders, - templateLoaderPath + `??vue-loader-options`, - ...preLoaders - ]) - // console.log(request) - // the template compiler uses esm exports - return `export * from ${request}` - } - - // if a custom block has no other matching loader other than vue-loader itself - // or cache-loader, we should ignore it - if (query.type === `custom` && shouldIgnoreCustomBlock(loaders)) { - return `` - } - - // When the user defines a rule that has only resourceQuery but no test, - // both that rule and the cloned rule will match, resulting in duplicated - // loaders. Therefore it is necessary to perform a dedupe here. - const request = genRequest(loaders) - return `import mod from ${request}; export default mod; export * from ${request}` -} diff --git a/packages/vue-cli-plugin-hbuilderx/packages/webpack-uni-nvue-loader/lib/compileTemplate.js b/packages/vue-cli-plugin-hbuilderx/packages/webpack-uni-nvue-loader/lib/compileTemplate.js deleted file mode 100644 index 5e056dc5451e62df8a76d5c77df9e71f0c69cbc6..0000000000000000000000000000000000000000 --- a/packages/vue-cli-plugin-hbuilderx/packages/webpack-uni-nvue-loader/lib/compileTemplate.js +++ /dev/null @@ -1,114 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const assetUrl_1 = __importDefault(require("@vue/component-compiler-utils/dist/templateCompilerModules/assetUrl")); -const srcset_1 = __importDefault(require("@vue/component-compiler-utils/dist/templateCompilerModules/srcset")); -const consolidate = require('consolidate'); -const transpile = require('vue-template-es2015-compiler'); -function compileTemplate(options) { - const { preprocessLang } = options; - const preprocessor = preprocessLang && consolidate[preprocessLang]; - if (preprocessor) { - return actuallyCompile(Object.assign({}, options, { - source: preprocess(options, preprocessor) - })); - } - else if (preprocessLang) { - return { - code: `var render = function () {}\n` + `var staticRenderFns = []\n`, - source: options.source, - tips: [ - `Component ${options.filename} uses lang ${preprocessLang} for template. Please install the language preprocessor.` - ], - errors: [ - `Component ${options.filename} uses lang ${preprocessLang} for template, however it is not installed.` - ] - }; - } - else { - return actuallyCompile(options); - } -} -exports.compileTemplate = compileTemplate; -function preprocess(options, preprocessor) { - const { source, filename, preprocessOptions } = options; - const finalPreprocessOptions = Object.assign({ - filename - }, preprocessOptions); - // Consolidate exposes a callback based API, but the callback is in fact - // called synchronously for most templating engines. In our case, we have to - // expose a synchronous API so that it is usable in Jest transforms (which - // have to be sync because they are applied via Node.js require hooks) - let res, err; - preprocessor.render(source, finalPreprocessOptions, (_err, _res) => { - if (_err) - err = _err; - res = _res; - }); - if (err) - throw err; - return res; -} -function actuallyCompile(options) { - const { source, compiler, compilerOptions = {}, transpileOptions = {}, transformAssetUrls, isProduction = process.env.NODE_ENV === 'production', isFunctional = false, optimizeSSR = false, prettify = true } = options; - const compile = optimizeSSR && compiler.ssrCompile ? compiler.ssrCompile : compiler.compile; - let finalCompilerOptions = compilerOptions; - if (transformAssetUrls) { - const builtInModules = [ - transformAssetUrls === true - ? assetUrl_1.default() - : assetUrl_1.default(transformAssetUrls), - srcset_1.default() - ]; - finalCompilerOptions = Object.assign({}, compilerOptions, { - modules: [...builtInModules, ...(compilerOptions.modules || [])] - }); - } - const { render, staticRenderFns, tips, errors, '@render': recyclableRender } = compile(source, finalCompilerOptions); - if (errors && errors.length) { - return { - code: `var render = function () {}\n` + `var staticRenderFns = []\n`, - source, - tips, - errors - }; - } - else { - const finalTranspileOptions = Object.assign({}, transpileOptions, { - transforms: Object.assign({}, transpileOptions.transforms, { - stripWithFunctional: isFunctional - }) - }); - const toFunction = (code) => { - return `function (${isFunctional ? `_h,_vm` : ``}) {${code}}`; - }; - // transpile code with vue-template-es2015-compiler, which is a forked - // version of Buble that applies ES2015 transforms + stripping `with` usage - let code = transpile(`var __render__ = ${toFunction(render)}\n` + - (recyclableRender ? (`var __recyclableRender__ = ${toFunction(recyclableRender)}\n`) : '') + - `var __staticRenderFns__ = [${staticRenderFns.map(toFunction)}]`, finalTranspileOptions) + `\n`; - // #23 we use __render__ to avoid `render` not being prefixed by the - // transpiler when stripping with, but revert it back to `render` to - // maintain backwards compat - code = code.replace(/\s__(render|recyclableRender|staticRenderFns)__\s/g, ' $1 '); - if (!isProduction) { - // mark with stripped (this enables Vue to use correct runtime proxy - // detection) - code += `render._withStripped = true`; - if (prettify) { - code = require('prettier').format(code, { - semi: false, - parser: 'babel' - }); - } - } - return { - code, - source, - tips, - errors - }; - } -} diff --git a/packages/vue-cli-plugin-hbuilderx/packages/webpack-uni-nvue-loader/lib/styleInjection.js b/packages/vue-cli-plugin-hbuilderx/packages/webpack-uni-nvue-loader/lib/styleInjection.js deleted file mode 100644 index e684809bc2f40dbf41b4ba86ba221fe0448eb116..0000000000000000000000000000000000000000 --- a/packages/vue-cli-plugin-hbuilderx/packages/webpack-uni-nvue-loader/lib/styleInjection.js +++ /dev/null @@ -1,134 +0,0 @@ -const { attrsToQuery } = require('vue-loader/lib/codegen/utils') -const hotReloadAPIPath = JSON.stringify(require.resolve('vue-hot-reload-api')) -const nonWhitespaceRE = /\S+/ - -module.exports = function genStyleInjectionCode ( - loaderContext, - styles, - id, - resourcePath, - stringifyRequest, - needsHotReload, - needsExplicitInjection -) { - let styleImportsCode = `` - let styleInjectionCode = `` - let cssModulesHotReloadCode = `` - - let hasCSSModules = false - const cssModuleNames = new Map() - - function genStyleRequest (style, i) { - const src = style.src || resourcePath - const attrsQuery = attrsToQuery(style.attrs, 'css') - const inheritQuery = `&${loaderContext.resourceQuery.slice(1)}` - // make sure to only pass id when necessary so that we don't inject - // duplicate tags when multiple components import the same css file - const idQuery = style.scoped ? `&id=${id}` : `` - const query = `?vue&type=style&index=${i}${idQuery}${attrsQuery}${inheritQuery}` - return stringifyRequest(src + query) - } - - function genCSSModulesCode (style, request, i) { - hasCSSModules = true - - const moduleName = style.module === true ? '$style' : style.module - if (cssModuleNames.has(moduleName)) { - loaderContext.emitError(`CSS module name ${moduleName} is not unique!`) - } - cssModuleNames.set(moduleName, true) - - // `(vue-)style-loader` exports the name-to-hash map directly - // `css-loader` exports it in `.locals` - const locals = `(style${i}.locals || style${i})` - const name = JSON.stringify(moduleName) - - if (!needsHotReload) { - styleInjectionCode += `this[${name}] = ${locals}\n` - } else { - styleInjectionCode += ` - cssModules[${name}] = ${locals} - Object.defineProperty(this, ${name}, { - configurable: true, - get: function () { - return cssModules[${name}] - } - }) - ` - cssModulesHotReloadCode += ` - module.hot && module.hot.accept([${request}], function () { - var oldLocals = cssModules[${name}] - if (oldLocals) { - var newLocals = require(${request}) - if (JSON.stringify(newLocals) !== JSON.stringify(oldLocals)) { - cssModules[${name}] = newLocals - require(${hotReloadAPIPath}).rerender("${id}") - } - } - }) - ` - } - } - - // empty styles: with no `src` specified or only contains whitespaces - const isNotEmptyStyle = style => style.src || nonWhitespaceRE.test(style.content) - // explicit injection is needed in SSR (for critical CSS collection) - // or in Shadow Mode (for injection into shadow root) - // In these modes, vue-style-loader exports objects with the __inject__ - // method; otherwise we simply import the styles. - if (!needsExplicitInjection) { - styles.forEach((style, i) => { - // do not generate requests for empty styles - if (isNotEmptyStyle(style)) { - const request = genStyleRequest(style, i) - styleImportsCode += `import style${i} from ${request}\n` - if (style.module) genCSSModulesCode(style, request, i) - } - }) - } else { - styleInjectionCode = `if(!this.options.style){ - this.options.style = {} -} -if(Vue.prototype.__merge_style && Vue.prototype.__$appStyle__){ - Vue.prototype.__merge_style(Vue.prototype.__$appStyle__, this.options.style) -} -` - styles.forEach((style, i) => { - if (isNotEmptyStyle(style)) { - const request = genStyleRequest(style, i) - styleInjectionCode += ( - `if(Vue.prototype.__merge_style){ - Vue.prototype.__merge_style(require(${request}).default, this.options.style) - }else{ - Object.assign(this.options.style,require(${request}).default) - }\n`//fixed by xxxxxx 简单处理,与 weex-vue-loader 保持一致 - //`var style${i} = require(${request})\n` + - //`if (style${i}.__inject__) style${i}.__inject__(context)\n` - ) - if (style.module) genCSSModulesCode(style, request, i) - } - }) - } - - if (!needsExplicitInjection && !hasCSSModules) { - return styleImportsCode - } - - return ` -${styleImportsCode} -${hasCSSModules && needsHotReload ? `var cssModules = {}` : ``} -${needsHotReload ? `var disposed = false` : ``} - -function injectStyles () { - ${styleInjectionCode} -} - -${needsHotReload ? ` - module.hot && module.hot.dispose(function (data) { - disposed = true - }) -` : ``} - -${cssModulesHotReloadCode} - `.trim() -} diff --git a/packages/vue-cli-plugin-hbuilderx/packages/webpack-uni-nvue-loader/lib/templateLoader.js b/packages/vue-cli-plugin-hbuilderx/packages/webpack-uni-nvue-loader/lib/templateLoader.js deleted file mode 100644 index 249c72115bb0d16bb67b752e82e741a156165726..0000000000000000000000000000000000000000 --- a/packages/vue-cli-plugin-hbuilderx/packages/webpack-uni-nvue-loader/lib/templateLoader.js +++ /dev/null @@ -1,93 +0,0 @@ -const qs = require('querystring') -const loaderUtils = require('loader-utils') -const { compileTemplate } = require('@vue/component-compiler-utils') - -// Loader that compiles raw template into JavaScript functions. -// This is injected by the global pitcher (../pitch) for template -// selection requests initiated from vue files. -module.exports = function (source) { - const loaderContext = this - const query = qs.parse(this.resourceQuery.slice(1)) - - // although this is not the main vue-loader, we can get access to the same - // vue-loader options because we've set an ident in the plugin and used that - // ident to create the request for this loader in the pitcher. - const options = loaderUtils.getOptions(loaderContext) || {} - const { id } = query - const isServer = loaderContext.target === 'node' - const isProduction = options.productionMode || loaderContext.minimize || process.env.NODE_ENV === 'production' - const isFunctional = query.functional - - // allow using custom compiler via options - const compiler = options.compiler || require('vue-template-compiler') - - const compilerOptions = Object.assign({ - outputSourceRange: true - }, options.compilerOptions, { - scopeId: query.scoped ? `data-v-${id}` : null, - comments: query.comments, - filename: this.resourcePath // fixed by xxxxxx 传递 filename - }) - - // for vue-component-compiler - const finalOptions = { - source, - filename: this.resourcePath, - compiler, - compilerOptions, - // allow customizing behavior of vue-template-es2015-compiler - transpileOptions: options.transpileOptions, - transformAssetUrls: options.transformAssetUrls || true, - isProduction, - isFunctional, - optimizeSSR: isServer && options.optimizeSSR !== false, - prettify: options.prettify - } - - const compiled = compileTemplate(finalOptions) - - // tips - if (compiled.tips && compiled.tips.length) { - compiled.tips.forEach(tip => { - loaderContext.emitWarning(typeof tip === 'object' ? tip.msg : tip) - }) - } - - // errors - if (compiled.errors && compiled.errors.length) { - // 2.6 compiler outputs errors as objects with range - if (compiler.generateCodeFrame && finalOptions.compilerOptions.outputSourceRange) { - // TODO account for line offset in case template isn't placed at top - // of the file - loaderContext.emitError( - `\n\n Errors compiling template:\n\n` + - compiled.errors.map(({ msg, start, end }) => { - const frame = compiler.generateCodeFrame(source, start, end) - return ` ${msg}\n\n${pad(frame)}` - }).join(`\n\n`) + - '\n at ' + finalOptions.filename + ':0' // fixed by xxxxxx - ) - } else { - loaderContext.emitError( - `\n Error compiling template:\n${pad(compiled.source)}\n` + - compiled.errors.map(e => ` - ${e}`).join('\n') + - '\n at ' + finalOptions.filename + ':0' // fixed by xxxxxx - ) - } - } - - const { code } = compiled - - if(query.recyclable) {// fixed by xxxxxx - return code + `\nexport { render, recyclableRender, staticRenderFns }` - } - // finish with ESM exports - return code + `\nexport { render, staticRenderFns }` -} - -function pad (source) { - return source - .split(/\r?\n/) - .map(line => ` ${line}`) - .join('\n') -} diff --git a/packages/vue-cli-plugin-uni/lib/env.js b/packages/vue-cli-plugin-uni/lib/env.js index 3d0867117b587f2be9103e8298d3c13259c9d89d..b9a840c6e944b752da8de80b59cdddd02aaead8a 100644 --- a/packages/vue-cli-plugin-uni/lib/env.js +++ b/packages/vue-cli-plugin-uni/lib/env.js @@ -320,6 +320,13 @@ if ( } } +process.UNI_AUTO_COMPONENTS = [{ + test (str) { + return new RegExp('uni-(.*)').test(str) + }, + replacement: '@components/uni-$1/uni-$1.vue' +}] + runByHBuilderX && console.log(`正在编译中...`) module.exports = { diff --git a/packages/vue-cli-plugin-uni/lib/h5/compiler-options.js b/packages/vue-cli-plugin-uni/lib/h5/compiler-options.js index 0ee668b3fb2d5e7e0840d18131ca599a50fb625a..2ccf287395d6f827ad2b8595cdd2b53930baa20f 100644 --- a/packages/vue-cli-plugin-uni/lib/h5/compiler-options.js +++ b/packages/vue-cli-plugin-uni/lib/h5/compiler-options.js @@ -4,7 +4,7 @@ const { const { isUnaryTag -} = require('../util') +} = require('@dcloudio/uni-template-compiler/lib/util') const simplePathRE = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['[^']*?']|\["[^"]*?"]|\[\d+]|\[[A-Za-z_$][\w$]*])*$/ @@ -69,9 +69,7 @@ module.exports = { isUnaryTag, preserveWhitespace: false, modules: [require('../format-text'), { - preTransformNode (el, { - warn - }) { + preTransformNode (el, options) { fixBooleanAttribute(el) if (el.tag.indexOf('v-uni-') === 0) { addTag(el.tag.replace('v-uni-', '')) diff --git a/packages/vue-cli-plugin-uni/lib/mp-compiler-options.js b/packages/vue-cli-plugin-uni/lib/mp-compiler-options.js index d5c90f17b921d53cac0239ab1409bac063dfd121..d9593e6a31ebfa048f52e30524d956597f4a6134 100644 --- a/packages/vue-cli-plugin-uni/lib/mp-compiler-options.js +++ b/packages/vue-cli-plugin-uni/lib/mp-compiler-options.js @@ -3,10 +3,15 @@ const { convertStaticStyle } = require('@dcloudio/uni-cli-shared') +const { + isUnaryTag +} = require('@dcloudio/uni-template-compiler/lib/util') + module.exports = { + isUnaryTag, preserveWhitespace: false, modules: [require('./format-text'), { - preTransformNode (el, { + preTransformNode(el, { warn }) { if (el.attrsMap) { @@ -35,7 +40,7 @@ module.exports = { }) } }, - postTransformNode (el) { + postTransformNode(el) { if (process.env.UNI_PLATFORM === 'mp-alipay') { if (el.tag === 'slot') { if (!el.children.length) { diff --git a/packages/vue-cli-plugin-uni/lib/util.js b/packages/vue-cli-plugin-uni/lib/util.js index fd85fa57024c5892c14dd1b42f9515635e1023c1..06bccc219d3683b5052330347af6c9d6271e40e4 100644 --- a/packages/vue-cli-plugin-uni/lib/util.js +++ b/packages/vue-cli-plugin-uni/lib/util.js @@ -1,20 +1,5 @@ -function makeMap (str, expectsLowerCase) { - const map = Object.create(null) - const list = str.split(',') - for (let i = 0; i < list.length; i++) { - map[list[i]] = true - } - return expectsLowerCase - ? val => map[val.toLowerCase()] - : val => map[val] -} - let partialIdentifier = false module.exports = { - isUnaryTag: makeMap( - 'image,area,base,br,col,embed,frame,hr,img,input,isindex,keygen,' + - 'link,meta,param,source,track,wbr' - ), getPartialIdentifier () { if (!partialIdentifier) { partialIdentifier = { diff --git a/packages/vue-cli-plugin-uni/packages/vue-loader/lib/codegen/styleInjection.js b/packages/vue-cli-plugin-uni/packages/vue-loader/lib/codegen/styleInjection.js index 9a8cfc99aad54271edbaee6a994b5ece208a8beb..0e1cf0e737e38e1692259e9c64b9adc017936514 100644 --- a/packages/vue-cli-plugin-uni/packages/vue-loader/lib/codegen/styleInjection.js +++ b/packages/vue-cli-plugin-uni/packages/vue-loader/lib/codegen/styleInjection.js @@ -9,7 +9,7 @@ module.exports = function genStyleInjectionCode ( resourcePath, stringifyRequest, needsHotReload, - needsExplicitInjection + needsExplicitInjection // fixed by xxxxxx nvue 时,指定了 target 为 node,激活 needsExplicitInjection ) { let styleImportsCode = `` let styleInjectionCode = `` @@ -85,13 +85,25 @@ module.exports = function genStyleInjectionCode ( if (style.module) genCSSModulesCode(style, request, i) } }) - } else { + } else { // fixed by xxxxxx nvue style + styleInjectionCode = `if(!this.options.style){ + this.options.style = {} +} +if(Vue.prototype.__merge_style && Vue.prototype.__$appStyle__){ + Vue.prototype.__merge_style(Vue.prototype.__$appStyle__, this.options.style) +} +` styles.forEach((style, i) => { if (isNotEmptyStyle(style)) { const request = genStyleRequest(style, i) styleInjectionCode += ( - `var style${i} = require(${request})\n` + - `if (style${i}.__inject__) style${i}.__inject__(context)\n` + `if(Vue.prototype.__merge_style){ + Vue.prototype.__merge_style(require(${request}).default, this.options.style) + }else{ + Object.assign(this.options.style,require(${request}).default) + }\n`//fixed by xxxxxx 简单处理,与 weex-vue-loader 保持一致 + //`var style${i} = require(${request})\n` + + //`if (style${i}.__inject__) style${i}.__inject__(context)\n` ) if (style.module) genCSSModulesCode(style, request, i) } diff --git a/packages/vue-cli-plugin-uni/packages/vue-loader/lib/index.d.ts b/packages/vue-cli-plugin-uni/packages/vue-loader/lib/index.d.ts index b21db5c169b84c5d09be28fdcaafa1b39a23de92..28a4e3c5f28785cac7ac2644c6056e0e35a22b3f 100644 --- a/packages/vue-cli-plugin-uni/packages/vue-loader/lib/index.d.ts +++ b/packages/vue-cli-plugin-uni/packages/vue-loader/lib/index.d.ts @@ -1,5 +1,5 @@ import { Plugin } from 'webpack' -import { VueTemplateCompiler } from '@vue/component-compiler-utils/lib/types' +import { VueTemplateCompiler } from '@vue/component-compiler-utils/dist/types' import { CompilerOptions } from 'vue-template-compiler' declare namespace VueLoader { diff --git a/packages/vue-cli-plugin-uni/packages/vue-loader/lib/index.js b/packages/vue-cli-plugin-uni/packages/vue-loader/lib/index.js index 8023f68eb46540d73221c4c4fe10ebf631718220..3b9ac9a4f0dd2cfc1766e01e0d8322e475d84ea5 100644 --- a/packages/vue-cli-plugin-uni/packages/vue-loader/lib/index.js +++ b/packages/vue-cli-plugin-uni/packages/vue-loader/lib/index.js @@ -108,21 +108,26 @@ module.exports = function (source) { ) // template - let templateImport = `var render, staticRenderFns` + // fixed by xxxxxx (recyclable,auto components) + let recyclable + let templateImport = `var render, staticRenderFns, recyclableRender, components` let templateRequest if (descriptor.template) { + // fixed by xxxxxx + recyclable = options.isAppNVue && !!(template.attrs && template.attrs.recyclable) const src = descriptor.template.src || resourcePath const idQuery = `&id=${id}` const scopedQuery = hasScoped ? `&scoped=true` : `` const attrsQuery = attrsToQuery(descriptor.template.attrs) const query = `?vue&type=template${idQuery}${scopedQuery}${attrsQuery}${inheritQuery}` const request = templateRequest = stringifyRequest(src + query) - templateImport = `import { render, staticRenderFns } from ${request}` + // fixed by xxxxxx (auto components) + templateImport = `import { render, staticRenderFns, recyclableRender, components } from ${request}` } // script let scriptImport = `var script = {}` - if (descriptor.script) {// fixed by xxxxxx view 层的 script 在 script-loader 中提取自定义组件信息 + if (descriptor.script) { const src = descriptor.script.src || resourcePath const attrsQuery = attrsToQuery(descriptor.script.attrs, 'js') const query = `?vue&type=script${attrsQuery}${inheritQuery}` @@ -135,7 +140,8 @@ module.exports = function (source) { // styles let stylesCode = `` - if (options.isAppView && descriptor.styles.length) {// fixed by xxxxxx 仅限 view 层 + // fixed by xxxxxx 仅限 view 层 + if (!options.isAppService && descriptor.styles.length) { stylesCode = genStylesCode( loaderContext, descriptor.styles, @@ -146,7 +152,7 @@ module.exports = function (source) { isServer || isShadow // needs explicit injection? ) } - + // fixed by xxxxxx (injectStyles,auto components) let code = ` ${templateImport} ${scriptImport} @@ -159,10 +165,11 @@ var component = normalizer( render, staticRenderFns, ${hasFunctional ? `true` : `false`}, - ${/injectStyles/.test(stylesCode) ? `injectStyles` : `null`}, + ${options.isAppNVue ? `null`: (/injectStyles/.test(stylesCode) ? `injectStyles` : `null`)}, ${hasScoped ? JSON.stringify(id) : `null`}, ${isServer ? JSON.stringify(hash(request)) : `null`} - ${isShadow ? `,true` : ``} + ${isShadow ? `,true` : ``}, + components ) `.trim() + `\n` @@ -178,7 +185,10 @@ var component = normalizer( if (needsHotReload) { code += `\n` + genHotReloadCode(id, hasFunctional, templateRequest) } - + // fixed by xxxxxx (app-nvue injectStyles) + if (options.isAppNVue && /injectStyles/.test(stylesCode)) { + code +=`\ninjectStyles.call(component)` + } // Expose filename. This is used by the devtools and Vue runtime warnings. if (!isProduction) { // Expose the file's full path in development, so that it can be opened @@ -189,7 +199,9 @@ var component = normalizer( // For security reasons, only expose the file's basename in production. code += `\ncomponent.options.__file = ${JSON.stringify(filename)}` } - + if (recyclable) { // fixed by xxxxxx app-plus recyclable + code += `\nrecyclableRender && (component.options["@render"] = recyclableRender)` // fixed by xxxxxx + } code += `\nexport default component.exports` // console.log(code) return code diff --git a/packages/vue-cli-plugin-uni/packages/vue-loader/lib/loaders/pitcher.js b/packages/vue-cli-plugin-uni/packages/vue-loader/lib/loaders/pitcher.js index 5cb3f46e238e56a5df6bf222701d73384af7a95a..35106445ef71d4b7b894f360c91487081fe48ed5 100644 --- a/packages/vue-cli-plugin-uni/packages/vue-loader/lib/loaders/pitcher.js +++ b/packages/vue-cli-plugin-uni/packages/vue-loader/lib/loaders/pitcher.js @@ -127,16 +127,20 @@ module.exports.pitch = function (remainingRequest) { // for templates: inject the template compiler & optional cache if (query.type === `template`) { const path = require('path') + // const cacheLoader = cacheDirectory && cacheIdentifier + // ? [`${require.resolve('cache-loader')}?${JSON.stringify({ + // // For some reason, webpack fails to generate consistent hash if we + // // use absolute paths here, even though the path is only used in a + // // comment. For now we have to ensure cacheDirectory is a relative path. + // cacheDirectory: (path.isAbsolute(cacheDirectory) + // ? path.relative(process.cwd(), cacheDirectory) + // : cacheDirectory).replace(/\\/g, '/'), + // cacheIdentifier: hash(cacheIdentifier) + '-vue-loader-template' + // })}`] + // : [] + // fixed by xxxxxx 定制 template cache const cacheLoader = cacheDirectory && cacheIdentifier - ? [`cache-loader?${JSON.stringify({ - // For some reason, webpack fails to generate consistent hash if we - // use absolute paths here, even though the path is only used in a - // comment. For now we have to ensure cacheDirectory is a relative path. - cacheDirectory: (path.isAbsolute(cacheDirectory) - ? path.relative(process.cwd(), cacheDirectory) - : cacheDirectory).replace(/\\/g, '/'), - cacheIdentifier: hash(cacheIdentifier) + '-vue-loader-template' - })}`] + ? [`${require.resolve('cache-loader')}??uni-cache-loader-template-options`] : [] const preLoaders = loaders.filter(isPreLoader) diff --git a/packages/vue-cli-plugin-uni/packages/vue-loader/lib/loaders/templateLoader.js b/packages/vue-cli-plugin-uni/packages/vue-loader/lib/loaders/templateLoader.js index 57bab4e97733cb31f3655f90480d05efcb019cca..ada42e96bd480c4765d9d5271394cafacf8803b5 100644 --- a/packages/vue-cli-plugin-uni/packages/vue-loader/lib/loaders/templateLoader.js +++ b/packages/vue-cli-plugin-uni/packages/vue-loader/lib/loaders/templateLoader.js @@ -64,21 +64,21 @@ module.exports = function (source) { const frame = compiler.generateCodeFrame(source, start, end) return ` ${msg}\n\n${pad(frame)}` }).join(`\n\n`) + - '\n' + '\n at ' + finalOptions.filename + ':0' // fixed by xxxxxx ) } else { loaderContext.emitError( `\n Error compiling template:\n${pad(compiled.source)}\n` + compiled.errors.map(e => ` - ${e}`).join('\n') + - '\n' + '\n at ' + finalOptions.filename + ':0' // fixed by xxxxxx ) } } const { code } = compiled - - // finish with ESM exports - return code + `\nexport { render, staticRenderFns }` + // fixed by xxxxxx recyclableRender, components + // finish with ESM exports + return code + `\nexport { render, staticRenderFns, recyclableRender, components }` } function pad (source) { diff --git a/packages/vue-cli-plugin-uni/packages/vue-loader/lib/plugin-webpack4.js b/packages/vue-cli-plugin-uni/packages/vue-loader/lib/plugin-webpack4.js new file mode 100644 index 0000000000000000000000000000000000000000..77fb6568144fc9f0f0ace0b98d435146555d8b4f --- /dev/null +++ b/packages/vue-cli-plugin-uni/packages/vue-loader/lib/plugin-webpack4.js @@ -0,0 +1,157 @@ +const qs = require('querystring') +const RuleSet = require('webpack/lib/RuleSet') + +const id = 'vue-loader-plugin' +const NS = 'vue-loader' + +class VueLoaderPlugin { + apply (compiler) { + // add NS marker so that the loader can detect and report missing plugin + if (compiler.hooks) { + // webpack 4 + compiler.hooks.compilation.tap(id, compilation => { + const normalModuleLoader = compilation.hooks.normalModuleLoader + normalModuleLoader.tap(id, loaderContext => { + loaderContext[NS] = true + }) + }) + } else { + // webpack < 4 + compiler.plugin('compilation', compilation => { + compilation.plugin('normal-module-loader', loaderContext => { + loaderContext[NS] = true + }) + }) + } + + // use webpack's RuleSet utility to normalize user rules + const rawRules = compiler.options.module.rules + const { rules } = new RuleSet(rawRules) + + // find the rule that applies to vue files + let vueRuleIndex = rawRules.findIndex(createMatcher(`foo.vue`)) + if (vueRuleIndex < 0) { + vueRuleIndex = rawRules.findIndex(createMatcher(`foo.vue.html`)) + } + const vueRule = rules[vueRuleIndex] + + if (!vueRule) { + throw new Error( + `[VueLoaderPlugin Error] No matching rule for .vue files found.\n` + + `Make sure there is at least one root-level rule that matches .vue or .vue.html files.` + ) + } + + if (vueRule.oneOf) { + throw new Error( + `[VueLoaderPlugin Error] vue-loader 15 currently does not support vue rules with oneOf.` + ) + } + + // get the normlized "use" for vue files + const vueUse = vueRule.use + // get vue-loader options + const vueLoaderUseIndex = vueUse.findIndex(u => { + return /^vue-loader|(\/|\\|@)vue-loader/.test(u.loader) + }) + + if (vueLoaderUseIndex < 0) { + throw new Error( + `[VueLoaderPlugin Error] No matching use for vue-loader is found.\n` + + `Make sure the rule matching .vue files include vue-loader in its use.` + ) + } + + // make sure vue-loader options has a known ident so that we can share + // options by reference in the template-loader by using a ref query like + // template-loader??vue-loader-options + const vueLoaderUse = vueUse[vueLoaderUseIndex] + vueLoaderUse.ident = 'vue-loader-options' + vueLoaderUse.options = vueLoaderUse.options || {} + + // for each user rule (expect the vue rule), create a cloned rule + // that targets the corresponding language blocks in *.vue files. + const clonedRules = rules + .filter(r => r !== vueRule) + .map(cloneRule) + + // global pitcher (responsible for injecting template compiler loader & CSS + // post loader) + const pitcher = { + loader: require.resolve('./loaders/pitcher'), + resourceQuery: query => { + const parsed = qs.parse(query.slice(1)) + return parsed.vue != null + }, + options: { + cacheDirectory: vueLoaderUse.options.cacheDirectory, + cacheIdentifier: vueLoaderUse.options.cacheIdentifier + } + } + + // replace original rules + compiler.options.module.rules = [ + pitcher, + ...clonedRules, + ...rules + ] + } +} + +function createMatcher (fakeFile) { + return (rule, i) => { + // #1201 we need to skip the `include` check when locating the vue rule + const clone = Object.assign({}, rule) + delete clone.include + const normalized = RuleSet.normalizeRule(clone, {}, '') + return ( + !rule.enforce && + normalized.resource && + normalized.resource(fakeFile) + ) + } +} + +function cloneRule (rule) { + const { resource, resourceQuery } = rule + // Assuming `test` and `resourceQuery` tests are executed in series and + // synchronously (which is true based on RuleSet's implementation), we can + // save the current resource being matched from `test` so that we can access + // it in `resourceQuery`. This ensures when we use the normalized rule's + // resource check, include/exclude are matched correctly. + let currentResource + const res = Object.assign({}, rule, { + resource: { + test: resource => { + currentResource = resource + return true + } + }, + resourceQuery: query => { + const parsed = qs.parse(query.slice(1)) + if (parsed.vue == null) { + return false + } + if (resource && parsed.lang == null) { + return false + } + const fakeResourcePath = `${currentResource}.${parsed.lang}` + if (resource && !resource(fakeResourcePath)) { + return false + } + if (resourceQuery && !resourceQuery(query)) { + return false + } + return true + } + }) + + if (rule.oneOf) { + res.oneOf = rule.oneOf.map(cloneRule) + } + + return res +} + +VueLoaderPlugin.NS = NS +module.exports = VueLoaderPlugin diff --git a/packages/vue-cli-plugin-uni/packages/vue-loader/lib/plugin-webpack5.js b/packages/vue-cli-plugin-uni/packages/vue-loader/lib/plugin-webpack5.js new file mode 100644 index 0000000000000000000000000000000000000000..a3ec14dff3d016ca5b6a5960f7703d176a39f58a --- /dev/null +++ b/packages/vue-cli-plugin-uni/packages/vue-loader/lib/plugin-webpack5.js @@ -0,0 +1,193 @@ +const qs = require('querystring') +const id = 'vue-loader-plugin' +const NS = 'vue-loader' +const BasicEffectRulePlugin = require('webpack/lib/rules/BasicEffectRulePlugin') +const BasicMatcherRulePlugin = require('webpack/lib/rules/BasicMatcherRulePlugin') +const RuleSetCompiler = require('webpack/lib/rules/RuleSetCompiler') +const UseEffectRulePlugin = require('webpack/lib/rules/UseEffectRulePlugin') + +const ruleSetCompiler = new RuleSetCompiler([ + new BasicMatcherRulePlugin('test', 'resource'), + new BasicMatcherRulePlugin('include', 'resource'), + new BasicMatcherRulePlugin('exclude', 'resource', true), + new BasicMatcherRulePlugin('resource'), + new BasicMatcherRulePlugin('conditions'), + new BasicMatcherRulePlugin('resourceQuery'), + new BasicMatcherRulePlugin('realResource'), + new BasicMatcherRulePlugin('issuer'), + new BasicMatcherRulePlugin('compiler'), + new BasicEffectRulePlugin('type'), + new BasicEffectRulePlugin('sideEffects'), + new BasicEffectRulePlugin('parser'), + new BasicEffectRulePlugin('resolve'), + new UseEffectRulePlugin() +]) + +class VueLoaderPlugin { + apply (compiler) { + // add NS marker so that the loader can detect and report missing plugin + compiler.hooks.compilation.tap(id, compilation => { + const normalModuleLoader = require('webpack/lib/NormalModule').getCompilationHooks(compilation).loader + normalModuleLoader.tap(id, loaderContext => { + loaderContext[NS] = true + }) + }) + + const rules = compiler.options.module.rules + let rawVueRules + let vueRules = [] + + for (const rawRule of rules) { + // skip the `include` check when locating the vue rule + const clonedRawRule = Object.assign({}, rawRule) + delete clonedRawRule.include + + const ruleSet = ruleSetCompiler.compile([{ + rules: [clonedRawRule] + }]) + vueRules = ruleSet.exec({ + resource: 'foo.vue' + }) + + if (!vueRules.length) { + vueRules = ruleSet.exec({ + resource: 'foo.vue.html' + }) + } + if (vueRules.length > 0) { + if (rawRule.oneOf) { + throw new Error( + `[VueLoaderPlugin Error] vue-loader 15 currently does not support vue rules with oneOf.` + ) + } + rawVueRules = rawRule + break + } + } + if (!vueRules.length) { + throw new Error( + `[VueLoaderPlugin Error] No matching rule for .vue files found.\n` + + `Make sure there is at least one root-level rule that matches .vue or .vue.html files.` + ) + } + + // get the normlized "use" for vue files + const vueUse = vueRules.filter(rule => rule.type === 'use').map(rule => rule.value) + + // get vue-loader options + const vueLoaderUseIndex = vueUse.findIndex(u => { + return /^vue-loader|(\/|\\|@)vue-loader/.test(u.loader) + }) + + if (vueLoaderUseIndex < 0) { + throw new Error( + `[VueLoaderPlugin Error] No matching use for vue-loader is found.\n` + + `Make sure the rule matching .vue files include vue-loader in its use.` + ) + } + + // make sure vue-loader options has a known ident so that we can share + // options by reference in the template-loader by using a ref query like + // template-loader??vue-loader-options + const vueLoaderUse = vueUse[vueLoaderUseIndex] + vueLoaderUse.ident = 'vue-loader-options' + vueLoaderUse.options = vueLoaderUse.options || {} + + // for each user rule (expect the vue rule), create a cloned rule + // that targets the corresponding language blocks in *.vue files. + const refs = new Map() + const clonedRules = rules + .filter(r => r !== rawVueRules) + .map((rawRule) => cloneRule(rawRule, refs)) + + // fix conflict with config.loader and config.options when using config.use + delete rawVueRules.loader + delete rawVueRules.options + rawVueRules.use = vueUse + + // global pitcher (responsible for injecting template compiler loader & CSS + // post loader) + const pitcher = { + loader: require.resolve('./loaders/pitcher'), + resourceQuery: query => { + const parsed = qs.parse(query.slice(1)) + return parsed.vue != null + }, + options: { + cacheDirectory: vueLoaderUse.options.cacheDirectory, + cacheIdentifier: vueLoaderUse.options.cacheIdentifier + } + } + + // replace original rules + compiler.options.module.rules = [ + pitcher, + ...clonedRules, + ...rules + ] + } +} + +function cloneRule (rawRule, refs) { + const rules = ruleSetCompiler.compileRules('ruleSet', [{ + rules: [rawRule] + }], refs) + let currentResource + + const conditions = rules[0].rules + .map(rule => rule.conditions) + // shallow flat + .reduce((prev, next) => prev.concat(next), []) + + // do not process rule with enforce + if (!rawRule.enforce) { + const ruleUse = rules[0].rules + .map(rule => rule.effects + .filter(effect => effect.type === 'use') + .map(effect => effect.value) + ) + // shallow flat + .reduce((prev, next) => prev.concat(next), []) + + // fix conflict with config.loader and config.options when using config.use + delete rawRule.loader + delete rawRule.options + rawRule.use = ruleUse + } + + const res = Object.assign({}, rawRule, { + resource: resources => { + currentResource = resources + return true + }, + resourceQuery: query => { + const parsed = qs.parse(query.slice(1)) + if (parsed.vue == null) { + return false + } + if (!conditions) { + return false + } + const fakeResourcePath = `${currentResource}.${parsed.lang}` + for (const condition of conditions) { + // add support for resourceQuery + const request = condition.property === 'resourceQuery' ? query : fakeResourcePath + if (condition && !condition.fn(request)) { + return false + } + } + return true + } + }) + + delete res.test + + if (rawRule.oneOf) { + res.oneOf = rawRule.oneOf.map(rule => cloneRule(rule, refs)) + } + + return res +} + +VueLoaderPlugin.NS = NS +module.exports = VueLoaderPlugin diff --git a/packages/vue-cli-plugin-uni/packages/vue-loader/lib/plugin.js b/packages/vue-cli-plugin-uni/packages/vue-loader/lib/plugin.js index a5d91a2f289c69a63630576be470836a7f7a3d77..f9bbb0d7d353b70a799c647e9519beb3f41f0b0b 100644 --- a/packages/vue-cli-plugin-uni/packages/vue-loader/lib/plugin.js +++ b/packages/vue-cli-plugin-uni/packages/vue-loader/lib/plugin.js @@ -1,163 +1,12 @@ -const qs = require('querystring') -const RuleSet = require('webpack/lib/RuleSet') - -const id = 'vue-loader-plugin' -const NS = 'vue-loader' - -class VueLoaderPlugin { - apply (compiler) { - // add NS marker so that the loader can detect and report missing plugin - if (compiler.hooks) { - // webpack 4 - compiler.hooks.compilation.tap(id, compilation => { - let normalModuleLoader - if (Object.isFrozen(compilation.hooks)) { - // webpack 5 - normalModuleLoader = require('webpack/lib/NormalModule').getCompilationHooks(compilation).loader - } else { - normalModuleLoader = compilation.hooks.normalModuleLoader - } - normalModuleLoader.tap(id, loaderContext => { - loaderContext[NS] = true - }) - }) - } else { - // webpack < 4 - compiler.plugin('compilation', compilation => { - compilation.plugin('normal-module-loader', loaderContext => { - loaderContext[NS] = true - }) - }) - } - - // use webpack's RuleSet utility to normalize user rules - const rawRules = compiler.options.module.rules - const { rules } = new RuleSet(rawRules) - - // find the rule that applies to vue files - let vueRuleIndex = rawRules.findIndex(createMatcher(`foo.vue`)) - if (vueRuleIndex < 0) { - vueRuleIndex = rawRules.findIndex(createMatcher(`foo.vue.html`)) - } - const vueRule = rules[vueRuleIndex] - - if (!vueRule) { - throw new Error( - `[VueLoaderPlugin Error] No matching rule for .vue files found.\n` + - `Make sure there is at least one root-level rule that matches .vue or .vue.html files.` - ) - } - - if (vueRule.oneOf) { - throw new Error( - `[VueLoaderPlugin Error] vue-loader 15 currently does not support vue rules with oneOf.` - ) - } - - // get the normlized "use" for vue files - const vueUse = vueRule.use - // get vue-loader options - const vueLoaderUseIndex = vueUse.findIndex(u => { - return /^vue-loader|(\/|\\|@)vue-loader/.test(u.loader) - }) - - if (vueLoaderUseIndex < 0) { - throw new Error( - `[VueLoaderPlugin Error] No matching use for vue-loader is found.\n` + - `Make sure the rule matching .vue files include vue-loader in its use.` - ) - } - - // make sure vue-loader options has a known ident so that we can share - // options by reference in the template-loader by using a ref query like - // template-loader??vue-loader-options - const vueLoaderUse = vueUse[vueLoaderUseIndex] - vueLoaderUse.ident = 'vue-loader-options' - vueLoaderUse.options = vueLoaderUse.options || {} - - // for each user rule (expect the vue rule), create a cloned rule - // that targets the corresponding language blocks in *.vue files. - const clonedRules = rules - .filter(r => r !== vueRule) - .map(cloneRule) - - // global pitcher (responsible for injecting template compiler loader & CSS - // post loader) - const pitcher = { - loader: require.resolve('./loaders/pitcher'), - resourceQuery: query => { - const parsed = qs.parse(query.slice(1)) - return parsed.vue != null - }, - options: { - cacheDirectory: vueLoaderUse.options.cacheDirectory, - cacheIdentifier: vueLoaderUse.options.cacheIdentifier - } - } - - // replace original rules - compiler.options.module.rules = [ - pitcher, - ...clonedRules, - ...rules - ] - } -} - -function createMatcher (fakeFile) { - return (rule, i) => { - // #1201 we need to skip the `include` check when locating the vue rule - const clone = Object.assign({}, rule) - delete clone.include - const normalized = RuleSet.normalizeRule(clone, {}, '') - return ( - !rule.enforce && - normalized.resource && - normalized.resource(fakeFile) - ) - } -} - -function cloneRule (rule) { - const { resource, resourceQuery } = rule - // Assuming `test` and `resourceQuery` tests are executed in series and - // synchronously (which is true based on RuleSet's implementation), we can - // save the current resource being matched from `test` so that we can access - // it in `resourceQuery`. This ensures when we use the normalized rule's - // resource check, include/exclude are matched correctly. - let currentResource - const res = Object.assign({}, rule, { - resource: { - test: resource => { - currentResource = resource - return true - } - }, - resourceQuery: query => { - const parsed = qs.parse(query.slice(1)) - if (parsed.vue == null) { - return false - } - if (resource && parsed.lang == null) { - return false - } - const fakeResourcePath = `${currentResource}.${parsed.lang}` - if (resource && !resource(fakeResourcePath)) { - return false - } - if (resourceQuery && !resourceQuery(query)) { - return false - } - return true - } - }) - - if (rule.oneOf) { - res.oneOf = rule.oneOf.map(cloneRule) - } - - return res +const webpack = require('webpack') +let VueLoaderPlugin = null + +if (webpack.version && webpack.version[0] > 4) { + // webpack5 and upper + VueLoaderPlugin = require('./plugin-webpack5') +} else { + // webpack4 and lower + VueLoaderPlugin = require('./plugin-webpack4') } -VueLoaderPlugin.NS = NS module.exports = VueLoaderPlugin diff --git a/packages/vue-cli-plugin-uni/packages/vue-loader/package.json b/packages/vue-cli-plugin-uni/packages/vue-loader/package.json index 8943087cd63f8f5144a41f648fea66250396bf9d..2ca8e99c3664a9199a923421adc2922e457fc393 100644 --- a/packages/vue-cli-plugin-uni/packages/vue-loader/package.json +++ b/packages/vue-cli-plugin-uni/packages/vue-loader/package.json @@ -1,6 +1,6 @@ { "name": "vue-loader", - "version": "15.7.1", + "version": "15.8.3", "description": "Vue single-file component loader for Webpack", "main": "lib/index.js", "typings": "lib/index.d.ts", @@ -34,10 +34,15 @@ }, "peerDependencies": { "css-loader": "*", - "webpack": "^4.1.0 || ^5.0.0-0" + "webpack": "^3.0.0 || ^4.1.0 || ^5.0.0-0" + }, + "peerDependenciesMeta": { + "cache-loader": { + "optional": true + } }, "dependencies": { - "@vue/component-compiler-utils": "^3.0.0", + "@vue/component-compiler-utils": "^3.1.0", "hash-sum": "^1.0.2", "loader-utils": "^1.1.0", "vue-hot-reload-api": "^2.3.0", 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 index c3c9139c22f12dc1a6252a807fcc5016c9946172..6a8104b4e746c5d1f7a74c622267fab652f1e620 100644 --- 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 @@ -13,5 +13,10 @@ module.exports = function(content, map) { const resourcePath = removeExt( normalizePath(path.relative(process.env.UNI_INPUT_DIR, this.resourcePath)) ) - return content + getUsingComponentsCode(resourcePath) + content = content + getUsingComponentsCode(resourcePath) + // TODO 自动导入 vue 组件(h5,小程序,app[vue,nvue]) + // 1. 需要 template-loader 解析出所有自定义组件() + // 2. 根据自定义组件信息生成引用代码 + // 3. node-modules中的组件不提供自动导入 + return content } diff --git a/src/core/runtime/mp/parser/data-parser.bak.js b/src/core/runtime/mp/parser/data-parser.bak.js deleted file mode 100644 index 82c91b9422aefb072d778dd0378db4154cd6f449..0000000000000000000000000000000000000000 --- a/src/core/runtime/mp/parser/data-parser.bak.js +++ /dev/null @@ -1,9 +0,0 @@ -export function parseData (data, vueComponentOptions) { - if (!data) { - return - } - const dataJson = JSON.stringify(data) - vueComponentOptions.data = function () { - return JSON.parse(dataJson) - } -} diff --git a/yarn.lock b/yarn.lock index df5a5cf2b00584bc255939f6e892c6530ed8a2fb..709b87a9ad35b728d46c598e58f2cf49469fdf1f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8912,9 +8912,9 @@ vue-style-loader@^4.1.0: hash-sum "^1.0.2" loader-utils "^1.0.2" -vue-template-compiler@^2.6.8: - version "2.6.10" - resolved "https://registry.npm.taobao.org/vue-template-compiler/download/vue-template-compiler-2.6.10.tgz#323b4f3495f04faa3503337a82f5d6507799c9cc" +vue-template-compiler@^2.6.11: + version "2.6.11" + resolved "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.11.tgz#c04704ef8f498b153130018993e56309d4698080" dependencies: de-indent "^1.0.2" he "^1.1.0" @@ -8923,9 +8923,9 @@ vue-template-es2015-compiler@^1.9.0: version "1.9.1" resolved "https://registry.npm.taobao.org/vue-template-es2015-compiler/download/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825" -vue@^2.6.8: - version "2.6.10" - resolved "https://registry.npm.taobao.org/vue/download/vue-2.6.10.tgz#a72b1a42a4d82a721ea438d1b6bf55e66195c637" +vue@^2.6.11: + version "2.6.11" + resolved "https://registry.npmjs.org/vue/-/vue-2.6.11.tgz#76594d877d4b12234406e84e35275c6d514125c5" w3c-hr-time@^1.0.1: version "1.0.1"