diff --git a/packages/mars-build/__test__/unit/compiler/template/template.test.js b/packages/mars-build/__test__/unit/compiler/template/template.test.js index ad27e76c..d990df8f 100644 --- a/packages/mars-build/__test__/unit/compiler/template/template.test.js +++ b/packages/mars-build/__test__/unit/compiler/template/template.test.js @@ -48,7 +48,7 @@ describe('[swan]template basic', () => { code: '', render: '({ render: function() { var _vm=this;var _h=_vm.$createElement;' + 'var _c=_vm._self._c||_h;return _c(\'view\',[_vm._t("aaa",null,' - + '{bbb:_vm.bbb,ccc:_vm.ccc}),_vm._t("default")],2) }, staticRenderFns: [] })' + + '{"bbb":_vm.bbb,"ccc":_vm.ccc}),_vm._t("default")],2) }, staticRenderFns: [] })' }; expect(code).toBe(expectRet.code); diff --git a/packages/mars-build/src/compiler/file/babel-plugin-relative-import.js b/packages/mars-build/src/compiler/file/babel-plugin-relative-import.js index 815f1484..9da83cdf 100644 --- a/packages/mars-build/src/compiler/file/babel-plugin-relative-import.js +++ b/packages/mars-build/src/compiler/file/babel-plugin-relative-import.js @@ -6,31 +6,32 @@ /* eslint-disable fecs-no-require */ const path = require('path'); +const {getModuleName} = require('../../helper/path'); +const {getModulePath} = require('./compileModules'); module.exports = function ({types: t}) { return { visitor: { ImportDeclaration(babelPath, state) { - const {filePath, cwd, modules, usedModules = {}, resolvedPaths = {}} = state.opts; - const moduleKeys = Object.keys(modules); + const {rPath, modules, usedModules = {}, compileNPM = false} = state.opts; const name = babelPath.node.source.value; - - const key = moduleKeys.find(key => (new RegExp('^' + key + '(/.*)?$')).test(name)); - if (key) { - const modulePath = path.join(cwd, modules[key].path); - let relativePath = path.relative(path.dirname(filePath), modulePath); + const modName = getModuleName(name); + if (modName && (compileNPM || modules[modName])) { + let modulePath = getModulePath(name, modules).replace(/\.js$/, ''); + let relativePath = path.join(rPath, modulePath); if (relativePath[0] !== '.') { relativePath = './' + relativePath; } - const resolvedPath = name.replace(key, relativePath); + const resolvedPath = name.replace(modName, relativePath); + usedModules[name] = { + modName, + path: modulePath, + resolvedPath + }; babelPath.node.source.value = resolvedPath; - resolvedPaths[name] = resolvedPath; - usedModules[name.replace(key, modules[key].path)] = key; } }, CallExpression(nodePath, state) { - const {filePath, cwd, modules, usedModules = {}, resolvedPaths = {}} = state.opts; - const moduleKeys = Object.keys(modules); const node = nodePath.node; const callee = node.callee; const arg = node.arguments[0]; @@ -39,21 +40,25 @@ module.exports = function ({types: t}) { return; } + const {rPath, modules, usedModules = {}, compileNPM = false} = state.opts; const name = arg.value; - - const key = moduleKeys.find(key => (new RegExp('^' + key + '(/.*)?$')).test(name)); - if (key) { - const modulePath = path.join(cwd, modules[key].path); - let relativePath = path.relative(path.dirname(filePath), modulePath); + const modName = getModuleName(name); + if (modName && (compileNPM || modules[modName])) { + let modulePath = getModulePath(name, modules).replace(/\.js$/, ''); + let relativePath = path.join(rPath, modulePath); if (relativePath[0] !== '.') { relativePath = './' + relativePath; } - const resolvedPath = name.replace(key, relativePath); + const resolvedPath = name.replace(modName, relativePath); + usedModules[name] = { + modName, + path: modulePath, + resolvedPath + }; nodePath.replaceWith( t.callExpression(callee, [t.stringLiteral(resolvedPath)]) ); - resolvedPaths[name] = resolvedPath; - usedModules[name.replace(key, modules[key].path)] = key; + // babelPath.node.source.value = resolvedPath; } } } diff --git a/packages/mars-build/src/compiler/file/base.js b/packages/mars-build/src/compiler/file/base.js index 94008e23..83606639 100644 --- a/packages/mars-build/src/compiler/file/base.js +++ b/packages/mars-build/src/compiler/file/base.js @@ -57,6 +57,7 @@ function getFileCompiler(compile, config) { source = await process(source, getExtProcessors(preprocessors, lang)); // compile options.path = file.path; + options.file = file; const result = await compile(source, options, fileOptions); // postprocessors let {code, ...rest} = result; diff --git a/packages/mars-build/src/compiler/file/compileModules.js b/packages/mars-build/src/compiler/file/compileModules.js index 0e2c1cda..979af05a 100644 --- a/packages/mars-build/src/compiler/file/compileModules.js +++ b/packages/mars-build/src/compiler/file/compileModules.js @@ -11,17 +11,17 @@ const fs = require('fs-extra'); const webpack = require('webpack'); const log = require('../../helper/log'); -const {getPathToCWD} = require('../../helper/path'); +const {getPathToCWD, getModuleName} = require('../../helper/path'); const path = require('path'); const modules = { '@marsjs/core': { needCompile: false, - path: './mars-core' + path: './mars-core/index.js' }, 'vuex': { needCompile: true, - path: './mars_modules/vuex' + path: './mars_modules/vuex/index.js' } }; @@ -34,16 +34,55 @@ const H5Modules = { const inProcessingModules = new Set(); +function getModulePath(modulePath, modules) { + const modName = getModuleName(modulePath); + if (modules[modName] && modules[modName].path) { + return modules[modName].path; + } + const entry = require.resolve(modulePath, { + paths: [process.cwd()] + }); + + modulePath = './mars_modules' + entry.slice(entry.lastIndexOf('node_modules')).replace('node_modules', ''); + return modulePath; +} + +function resolveComponentsPath(components, modules) { + Object.keys(components).forEach(key => { + const name = components[key]; + components[key] = (modules[name] && modules[name].resolvedPath) || name; + }); +} + +function getUIModules(components, target) { + const modules = {}; + Object.keys(components).forEach(key => { + const mod = components[key]; + if (mod[0] !== '.') { + const name = getModuleName(mod); + const path = `./mars_modules/${name}/dist/${target}`; + const realName = `${name}/dist/${target}`; + modules[name] = { + path, + realName, + type: 'ui' + }; + } + }); + return modules; +} + /** * compile * - * @param {string} val key - * @param {string} key key - * @param {string} destPath dest + * @param {string} key module key + * @param {string} val module output path + * @param {string} destPath dest dir path * @return {Promise} */ -function compile(val, key, destPath) { - if (!modules[key].needCompile) { +function compile(key, val, destPath) { + // const {modName, path, resolvedPath} = info; + if (modules[key] && !modules[key].needCompile) { return Promise.resolve(); } @@ -51,20 +90,12 @@ function compile(val, key, destPath) { paths: [process.cwd()] }); - let modulePath; - if (val === modules[key].path) { - // 直接写的包名,为了能引用到,生成为 index.js - modulePath = val + '/index.js'; - } - else { - modulePath = './mars_modules' + entry.slice(entry.lastIndexOf('node_modules')).replace('node_modules', ''); - } - + let modulePath = val.replace(/\.js$/, '') + '.js'; if (fs.existsSync(path.resolve(destPath, modulePath)) || inProcessingModules.has(entry)) { return Promise.resolve(); } - log.info('[compile:module]:', getPathToCWD(entry)); + log.info('[compile:module]:', getPathToCWD(entry), ' => ', modulePath); inProcessingModules.add(entry); return new Promise((resolve, reject) => { @@ -113,7 +144,7 @@ async function compileUIModules(uiModules, destPath) { const entry = coreEntry.replace('mars-core/index.js', ''); const dest = path.resolve(destPath, modPath); - log.info('[compile:ui-module]:', getPathToCWD(entry)); + log.info('[compile:ui-module]:', getPathToCWD(entry), '=>', dest); await fs.copy(entry, dest); const coreDestPath = path.resolve(destPath, 'mars-core'); @@ -130,5 +161,8 @@ module.exports = { compile, modules, H5Modules, - compileUIModules + compileUIModules, + resolveComponentsPath, + getUIModules, + getModulePath }; diff --git a/packages/mars-build/src/compiler/file/compiler.js b/packages/mars-build/src/compiler/file/compiler.js index 8e69be66..a1944251 100644 --- a/packages/mars-build/src/compiler/file/compiler.js +++ b/packages/mars-build/src/compiler/file/compiler.js @@ -30,7 +30,8 @@ const modules = compileModules.modules; */ async function compileJS(content, options) { const { - target + target, + file } = options; const buildConfig = options._config; @@ -42,16 +43,18 @@ async function compileJS(content, options) { JSON.stringify(process.env.NODE_ENV || 'development') ); + const destPath = path.resolve(buildConfig.dest.path); + const rPath = path.relative(path.dirname(file.path), file.base); let usedModules = {}; let res = transformSync(content, { plugins: [ [ path.resolve(__dirname, './babel-plugin-relative-import.js'), { - filePath: options.path, - cwd: path.resolve(process.cwd(), './src'), + rPath, modules, - usedModules + usedModules, + compileNPM: process.env.MARS_ENV_TARGET === 'wx' } ], 'minify-guarded-expressions', @@ -59,11 +62,14 @@ async function compileJS(content, options) { ] }); - const destPath = path.resolve(buildConfig.dest.path); const usedModuleKeys = Object.keys(usedModules); for (let i = 0; i < usedModuleKeys.length; i++) { - const item = usedModuleKeys[i]; - await compileModules.compile(item, usedModules[item], destPath); + const key = usedModuleKeys[i]; + const info = usedModules[key]; + const {path} = info; + // if (!uiModules[modName]) { + await compileModules.compile(key, path, destPath); + // } } return res; diff --git a/packages/mars-build/src/compiler/script/script-h5.js b/packages/mars-build/src/compiler/script/script-h5.js index d3fbe792..b2ee7669 100644 --- a/packages/mars-build/src/compiler/script/script-h5.js +++ b/packages/mars-build/src/compiler/script/script-h5.js @@ -16,6 +16,7 @@ const transformRouterPlugin = require('../../h5/transform/plugins/transformRoute const transformAppPlugin = require('../../h5/transform/plugins/transformAppPlugin'); const transformGetAppPlugin = require('../../h5/transform/plugins/transformGetAppPlugin'); const postTransformScriptPlugin = require('./babel-plugin-script-post'); + const MARS_ENV = process.env.MARS_ENV_TARGET || 'h5'; exports.preCompile = function (file) { @@ -138,8 +139,8 @@ exports.compileMain = function (content, options) { const path = require('path'); -const {getUIModules, resolveComponentsPath} = require('./script'); const compileModules = require('../file/compileModules'); +const {resolveComponentsPath, getUIModules} = compileModules; exports.compileScript = async function (content, options = {}) { if (!content) { @@ -151,7 +152,6 @@ exports.compileScript = async function (content, options = {}) { mpConfig, target, dest, - path: filePath, mars } = options; let baseOptions = {}; // 收集 config 和 components @@ -185,24 +185,25 @@ exports.compileScript = async function (content, options = {}) { content = new Buffer(scriptStr); const {config = {}, components = {}, enableConfig = null} = baseOptions; - const destPath = path.resolve(dest.path); const uiModules = getUIModules(components, target); - let resolvedPaths = {}; + const destPath = path.resolve(dest.path); + const rPath = path.relative(path.dirname(options.path), destPath); + + let usedMoudles = {}; content = babel.transform(content, { plugins: [ [ path.resolve(__dirname, '../file/babel-plugin-relative-import.js'), { - filePath, - cwd: path.resolve(process.cwd(), dest.path), + rPath, modules: Object.assign(compileModules.H5Modules, uiModules), - resolvedPaths + usedMoudles } ] ] }).code; - resolveComponentsPath(components, resolvedPaths); + resolveComponentsPath(components, usedMoudles); await compileModules.compileUIModules(uiModules, destPath); return {config, components, enableConfig, content}; diff --git a/packages/mars-build/src/compiler/script/script.js b/packages/mars-build/src/compiler/script/script.js index 940744f5..8207c789 100644 --- a/packages/mars-build/src/compiler/script/script.js +++ b/packages/mars-build/src/compiler/script/script.js @@ -14,7 +14,7 @@ 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; +const {resolveComponentsPath, getUIModules, modules} = compileModules; /** * compile script @@ -53,57 +53,47 @@ async function compile(source, options) { }) ] }); - // 处理完再进行minify,发现minify和定制的插件会有坑 let code = scriptRet.code; + const { + config = {}, + components = {}, + computedKeys = [], + moduleType = 'esm' + } = ret; + + const uiModules = getUIModules(components, target); + // 处理完再进行minify,发现minify和定制的插件会有坑 + const destPath = path.resolve(dest.path); + const rPath = path.relative(path.dirname(options.path), destPath); let usedModules = {}; const minifyScriptRet = transformSync(code, { plugins: [ [ path.resolve(__dirname, '../file/babel-plugin-relative-import.js'), { - filePath: options.path, - cwd: path.resolve(process.cwd(), dest.path), - modules, - usedModules + rPath, + modules: Object.assign({}, modules, uiModules), + usedModules, + compileNPM: process.env.MARS_ENV_TARGET === 'wx' } ], 'minify-guarded-expressions', 'minify-dead-code-elimination' ] }); + code = minifyScriptRet.code; - const destPath = path.resolve(dest.path); const usedModuleKeys = Object.keys(usedModules); for (let i = 0; i < usedModuleKeys.length; i++) { - const item = usedModuleKeys[i]; - await compileModules.compile(item, usedModules[item], destPath); + const key = usedModuleKeys[i]; + const info = usedModules[key]; + const {modName, path} = info; + if (!uiModules[modName]) { + await compileModules.compile(key, path, destPath); + } } - code = minifyScriptRet.code; - const { - config = {}, - components = {}, - computedKeys = [], - moduleType = 'esm' - } = ret; - - const uiModules = getUIModules(components, target); - let resolvedPaths = {}; - code = transformSync(code, { - plugins: [ - [ - path.resolve(__dirname, '../file/babel-plugin-relative-import.js'), - { - filePath: options.path, - cwd: path.resolve(process.cwd(), dest.path), - modules: uiModules, - resolvedPaths - } - ] - ] - }).code; - - resolveComponentsPath(components, resolvedPaths); + resolveComponentsPath(components, usedModules); await compileModules.compileUIModules(uiModules, destPath); return {code, config, components, computedKeys, moduleType}; @@ -128,33 +118,7 @@ async function postCompile(source, options) { return {code: scriptRet.code}; } -function resolveComponentsPath(components, resolvedPaths) { - Object.keys(components).forEach(key => { - const name = components[key]; - components[key] = resolvedPaths[name] || name; - }); -} - -function getUIModules(components, target) { - const modules = {}; - Object.keys(components).forEach(key => { - const mod = components[key]; - if (mod[0] !== '.') { - const name = getModuleName(mod); - const path = `mars_modules/${name}/dist/${target}`; - const realName = `${name}/dist/${target}`; - modules[name] = { - path, - realName - }; - } - }); - return modules; -} - module.exports = { compile, - postCompile, - getUIModules, - resolveComponentsPath + postCompile }; diff --git a/packages/mars-build/src/helper/log.js b/packages/mars-build/src/helper/log.js index 19b95277..f438a799 100644 --- a/packages/mars-build/src/helper/log.js +++ b/packages/mars-build/src/helper/log.js @@ -5,12 +5,13 @@ const chalk = require('chalk'); function print(args, level, labelColor) { - const [label, info = ''] = args; + const [label, info = '', ...rest] = args; + const target = process.env.MARS_ENV_TARGET; if (info instanceof Error) { - console[level](labelColor(label), labelColor(info.stack)); + console[level](chalk.yellow(`[${target}]`), labelColor(label), labelColor(info.stack)); } else { - console[level](labelColor(label), info); + console[level](chalk.yellow(`[${target}]`), labelColor(label), [info].concat(rest || []).join('')); } } diff --git a/packages/mars-build/src/helper/path.js b/packages/mars-build/src/helper/path.js index c3457ec1..b40ee446 100644 --- a/packages/mars-build/src/helper/path.js +++ b/packages/mars-build/src/helper/path.js @@ -27,6 +27,9 @@ function changeExt(filePath, ext) { } function getModuleName(mod) { + if (mod[0] === '.') { + return null; + } let [name, temp] = mod.split('/'); if (name[0] === '@') { name = `${name}/${temp}`; diff --git a/packages/mars-build/src/scripts/run.js b/packages/mars-build/src/scripts/run.js index 42b8c549..0b9b2cbb 100644 --- a/packages/mars-build/src/scripts/run.js +++ b/packages/mars-build/src/scripts/run.js @@ -15,6 +15,7 @@ const { // const getDefaultConf = require('./defaultConfig'); const getConfig = require('./getConfig'); +const log = require('../helper/log'); /** * getBuildTasks @@ -45,7 +46,7 @@ function clean(options = {}) { const config = getConfig(options); gulp.task('clean', getTaskClean(config, options)); - console.log('[start task] clean'); + log.info('[start task]', 'clean'); return gulp.start('clean'); } @@ -59,7 +60,7 @@ function build(options = {}) { const config = getConfig(options); const buildTasks = getBuildTasks(config, options); gulp.task('build', buildTasks); - console.log('[start task] build'); + log.info('[start task]', 'build'); return gulp.start('build'); } @@ -69,7 +70,7 @@ function watch(options = {}) { gulp.task('build', buildTasks); gulp.task('watch', ['build'], getTaskWatch(config, options)); - console.log('[start task] watch'); + log.info('[start task]', 'watch'); return gulp.start('watch'); }