diff --git a/packages/mars-build/src/compiler/script/babel-plugin-script-post.js b/packages/mars-build/src/compiler/script/babel-plugin-script-post.js new file mode 100644 index 00000000..a791838e --- /dev/null +++ b/packages/mars-build/src/compiler/script/babel-plugin-script-post.js @@ -0,0 +1,41 @@ +/** + * @file build + * @author zhangjingyuan02 + */ + +/* eslint-disable fecs-camelcase */ +/* eslint-disable babel/new-cap */ +module.exports = function getVisitor(options = {}) { + return ({types: t}) => { + const { + componentsInUsed + } = options; + return { + visitor: { + ImportDeclaration(path, state) { + const sourcePath = path.node.source; + if (sourcePath) { + Object.keys(componentsInUsed).forEach(comp => { + componentsInUsed[comp].declaration === sourcePath.value + && !componentsInUsed[comp].using + && path.remove(); + }); + } + }, + ObjectProperty(path, state) { + if (path.node.key.name !== 'components') { + return; + } + path.traverse({ + ObjectProperty(path, state) { + if (!componentsInUsed[path.node.key.name].using) { + path.remove(); + } + } + + }); + } + } + }; + }; +}; diff --git a/packages/mars-build/src/compiler/script/script.js b/packages/mars-build/src/compiler/script/script.js index c7641d19..8486ae82 100644 --- a/packages/mars-build/src/compiler/script/script.js +++ b/packages/mars-build/src/compiler/script/script.js @@ -12,6 +12,7 @@ const {transformSync} = require('@babel/core'); const {getModuleName} = require('../../helper/path'); const transformPlugin = require('./babel-plugin-script'); +const postTransformPlugin = require('./babel-plugin-script-post'); const compileModules = require('../file/compileModules'); const modules = compileModules.modules; @@ -52,7 +53,6 @@ async function compile(source, options) { }); // 处理完再进行minify,发现minify和定制的插件会有坑 let code = scriptRet.code; - let usedModules = {}; const minifyScriptRet = transformSync(code, { plugins: [ @@ -107,6 +107,25 @@ async function compile(source, options) { return {code, config, components, computedKeys, moduleType}; } +/** + * postcompile script + * + * @param {string} source source + * @param {mars.options} options options + * @return {mars.script.compileScriptResult} + */ +async function postCompile(source, options) { + const {componentsInUsed} = options; + const scriptRet = transformSync(source, { + plugins: [ + postTransformPlugin({ + componentsInUsed + }) + ] + }); + return {code: scriptRet.code}; +} + function resolveComponentsPath(components, resolvedPaths) { Object.keys(components).forEach(key => { const name = components[key]; @@ -133,6 +152,7 @@ function getUIModules(components, target) { module.exports = { compile, + postCompile, getUIModules, resolveComponentsPath }; diff --git a/packages/mars-build/src/compiler/sfc/compiler.js b/packages/mars-build/src/compiler/sfc/compiler.js index 463e4217..b097c5ff 100644 --- a/packages/mars-build/src/compiler/sfc/compiler.js +++ b/packages/mars-build/src/compiler/sfc/compiler.js @@ -9,8 +9,13 @@ const {getFileCompilers} = require('../file/base'); exports.compile = async function compile(file, options) { const {template, script, styles, config: configFile} = file; const {compilers, isApp, fPath, target, coreRelativePath, baseName} = options; - const {templateCompiler, scriptCompiler, styleCompiler, configCompiler} = getFileCompilers(compilers, options); - + const { + templateCompiler, + scriptCompiler, + scriptPostCompiler, + styleCompiler, + configCompiler + } = getFileCompilers(compilers, options); const {components, config, computedKeys, moduleType} = await scriptCompiler(script, { isApp, coreRelativePath, @@ -18,12 +23,15 @@ exports.compile = async function compile(file, options) { renderStr: !isApp ? renderFunctionName : null, dest: options._config.dest }); - // app.vue has no template if (!isApp) { - const {render} = await templateCompiler(template, { + const {render, componentsInUsed} = await templateCompiler(template, { components, - computedKeys + computedKeys, + target + }); + await scriptPostCompiler(script, { + componentsInUsed }); script.appendContent( `;\nfunction ${renderFunctionName}() {return ${render + '.render.bind(this)()'};\n}` diff --git a/packages/mars-build/src/compiler/template/index.js b/packages/mars-build/src/compiler/template/index.js index cc3653c4..59ea4f17 100644 --- a/packages/mars-build/src/compiler/template/index.js +++ b/packages/mars-build/src/compiler/template/index.js @@ -11,14 +11,14 @@ exports.getCompiler = function getCompiler(marker, transformer, generater, target) { return function compiler(source, options) { - let {ast, render} = marker(source, options); + let {ast, render, componentsInUsed} = marker(source, options); let {ast: myAst} = transformer(ast, options); options = Object.assign(options, { target }); let code = generater(myAst, options); - return {render, code}; + return {render, code, componentsInUsed}; }; }; diff --git a/packages/mars-build/src/compiler/template/mark-component.js b/packages/mars-build/src/compiler/template/mark-component.js index c7096804..736bac16 100644 --- a/packages/mars-build/src/compiler/template/mark-component.js +++ b/packages/mars-build/src/compiler/template/mark-component.js @@ -9,6 +9,7 @@ const {compile: compileTemplate} = require('vue-template-compiler/build'); const transpile = require('vue-template-es2015-compiler'); +const customTemplate = 'template-mars'; function getIterator(node) { if (!node) { @@ -30,14 +31,50 @@ function isInFor(el) { return isInFor(el.parent); } -function getMarkNode(options) { - let {components} = options; +// 判断租先节点是否含有 template-mars target非当前环境,如果含有,则收集ast tag +function checkExtraEnvComponent(ast, target) { + let parent = ast.parent; + if (parent) { + if (parent.tag === customTemplate && parent.attrsMap && parent.attrsMap.target !== target) { + return true; + } + else { + return checkExtraEnvComponent(parent); + } + } + return false; +} + +// 找出在在当前环境中使用的组件 +function findUsefulComponent(ast, components, target, componentsInUsed) { + const tag = ast.tag; + const children = ast.children; + if (components[tag]) { + componentsInUsed[tag].using = true; + } + if (children) { + children.forEach(child => { + if (child.tag === customTemplate && child.attrsMap.target !== target) { + return; + } + else { + findUsefulComponent(child, components, target, componentsInUsed); + } + }); + } +} + +function getMarkNode(options, componentsInUsed = {}) { + let {components, target} = options; let compIdCounter = 0; return function markNode(el, options) { - const tag = el.tag; const isComp = components && components[tag]; el.isComp = isComp; + // 找出 template-mars 其他target下的组件,进行标记 + if (checkExtraEnvComponent(el, target || process.env.MARS_ENV_TARGET) && components[tag]) { + componentsInUsed[tag].using = false; + } if (el.attrsMap['v-for'] && !el.iterator1) { el.iterator1 = 'index'; @@ -156,6 +193,21 @@ function getPostTrans(options) { } module.exports = function mark(source, options) { + const { + components, + target + } = options; + + let componentsInUsed = {}; + Object.keys(components).forEach(name => { + if (!componentsInUsed[name]) { + componentsInUsed[name] = { + using: false, + declaration: components[name] + }; + } + }); + const { ast, render, @@ -165,17 +217,17 @@ module.exports = function mark(source, options) { preserveWhitespace: false, modules: [ { - transformNode: getMarkNode(options), + transformNode: getMarkNode(options, componentsInUsed), postTransformNode: getPostTrans(options), genData: getGenData(options) } ] }); - + findUsefulComponent(ast, components, target, componentsInUsed); let code = `({ render: function() { ${render} }, staticRenderFns: [\ ${staticRenderFns.map(fn => `function() { ${fn} },)}`)}\ ] })`; code = transpile(code); - return {ast, render: code, errors}; + return {ast, render: code, errors, componentsInUsed}; }; diff --git a/packages/mars-build/src/gulp-mars-swan.js b/packages/mars-build/src/gulp-mars-swan.js index 8e1f8cb4..8c283ff1 100644 --- a/packages/mars-build/src/gulp-mars-swan.js +++ b/packages/mars-build/src/gulp-mars-swan.js @@ -19,6 +19,7 @@ const {transform} = require('./swan/transform/index'); const templateCompiler = getCompiler(mark, transform, generate, 'swan'); const styleCompiler = require('./compiler/style/style').compile; const scriptCompiler = require('./compiler/script/script').compile; +const scriptPostCompiler = require('./compiler/script/script').postCompile; const configCompiler = require('./compiler/script/config').compile; const {FILE_SUFFIX} = require('./helper/config'); @@ -26,6 +27,7 @@ const {FILE_SUFFIX} = require('./helper/config'); const compilers = { templateCompiler, styleCompiler, + scriptPostCompiler, scriptCompiler, configCompiler }; diff --git a/packages/mars-build/src/gulp-mars-wxml.js b/packages/mars-build/src/gulp-mars-wxml.js index 8cba663f..bb792fc4 100644 --- a/packages/mars-build/src/gulp-mars-wxml.js +++ b/packages/mars-build/src/gulp-mars-wxml.js @@ -30,6 +30,7 @@ const {transform} = require('./wx/compiler/index'); const templateCompiler = getCompiler(mark, transform, generate, 'wx'); const styleCompiler = require('./compiler/style/style').compile; const scriptCompiler = require('./compiler/script/script').compile; +const scriptPostCompiler = require('./compiler/script/script').postCompile; const configCompiler = require('./compiler/script/config').compile; const {FILE_SUFFIX} = require('./helper/config'); @@ -38,6 +39,7 @@ const compilers = { templateCompiler, styleCompiler, scriptCompiler, + scriptPostCompiler, configCompiler }; diff --git a/packages/mars-build/src/h5/template/MarsApp.vue b/packages/mars-build/src/h5/template/MarsApp.vue index 7a964084..7221ef03 100644 --- a/packages/mars-build/src/h5/template/MarsApp.vue +++ b/packages/mars-build/src/h5/template/MarsApp.vue @@ -161,7 +161,7 @@ export default { }, computed: { tabBarHeight() { - return this.tabList.some(item => item.pagePath === this.$route.path) ? 45 : 0; + return this.tabList.some(item => item.pagePath === this.$route.path) && this.customShowTabBar ? 45 : 0; } }, watch: { diff --git a/packages/mars-build/src/h5/transform/tag.js b/packages/mars-build/src/h5/transform/tag.js index 478da044..56b61eba 100644 --- a/packages/mars-build/src/h5/transform/tag.js +++ b/packages/mars-build/src/h5/transform/tag.js @@ -35,12 +35,25 @@ function toCamel(name) { return camelName.substring(0, 1).toUpperCase() + camelName.substring(1); } +// 判断租先节点是否含有 template-mars target=swan|wx,如果含有,则不收集该ast tag +function checkScopedTemplateIsH5(ast) { + let parent = ast.parent; + if (parent) { + if (parent.tag === 'template-mars' && parent.attrsMap && parent.attrsMap.target !== 'h5') { + return false; + } + else { + return checkScopedTemplateIsH5(parent); + } + } + return true; +} + module.exports = function (ast, compMap) { let tag = ast.tag; if (!tag) { return ast; } - if ( tag === customTemplate && ast.attrsMap.target === (process.env.MARS_ENV_TARGET || 'h5') @@ -67,6 +80,7 @@ module.exports = function (ast, compMap) { tagMap[tag] && !compMap[tagMap[tag]] && tagMap[tag] !== 'template' + && checkScopedTemplateIsH5(ast) ) { compMap[`${tagMap[tag]}`] = toCamel(tagMap[tag]); }