Skip to content

Commit

Permalink
feat(build): support use npm in wx
Browse files Browse the repository at this point in the history
  • Loading branch information
allen-zh committed Aug 8, 2019
1 parent 7a99e6b commit 9564c89
Show file tree
Hide file tree
Showing 10 changed files with 139 additions and 123 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ describe('[swan]template basic', () => {
code: '<view><slot name="aaa" var-slotProps="{{ {bbb: bbb,ccc: ccc} }}"></slot><slot></slot></view>',
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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand All @@ -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;
}
}
}
Expand Down
1 change: 1 addition & 0 deletions packages/mars-build/src/compiler/file/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
74 changes: 54 additions & 20 deletions packages/mars-build/src/compiler/file/compileModules.js
Original file line number Diff line number Diff line change
Expand Up @@ -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'
}
};

Expand All @@ -34,37 +34,68 @@ 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();
}

const entry = require.resolve(key, {
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) => {
Expand Down Expand Up @@ -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');
Expand All @@ -130,5 +161,8 @@ module.exports = {
compile,
modules,
H5Modules,
compileUIModules
compileUIModules,
resolveComponentsPath,
getUIModules,
getModulePath
};
20 changes: 13 additions & 7 deletions packages/mars-build/src/compiler/file/compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ const modules = compileModules.modules;
*/
async function compileJS(content, options) {
const {
target
target,
file
} = options;
const buildConfig = options._config;

Expand All @@ -42,28 +43,33 @@ 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',
'minify-dead-code-elimination'
]
});

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;
Expand Down
17 changes: 9 additions & 8 deletions packages/mars-build/src/compiler/script/script-h5.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand All @@ -151,7 +152,6 @@ exports.compileScript = async function (content, options = {}) {
mpConfig,
target,
dest,
path: filePath,
mars
} = options;
let baseOptions = {}; // 收集 config 和 components
Expand Down Expand Up @@ -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};
Expand Down

0 comments on commit 9564c89

Please sign in to comment.