Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vuex #46

Merged
merged 5 commits into from May 10, 2019
Merged

Vuex #46

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
68 changes: 66 additions & 2 deletions docs/guide/vue-features.md
Expand Up @@ -97,6 +97,70 @@ filters 可以在插值和 props 中使用,复杂表达式可以在插值、pr
`build@0.2.12` `core@0.2.6` 起支持过滤器(filters),暂时只支持局部定义过滤器。
:::

## 规模化
## Vuex

Mars 中使用 Vuex 的方法与 Vue 类似,首先在 app.vue 中引入 Vue 和 Vuex,并初始化:

> 由于 Mars 使用定制的 Vue ,因此务必**从 @marsjs/core 中引入 Vue**。

```javascript
import {Vue} from '@marsjs/core';
import Vuex from 'vuex';

Vue.use(Vuex);
```

之后创建一个 store:

```javascript
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++;
}

}
});
```

放在 app.vue 的 export 中:

```javascript
export default {
config: {
pages: [
'pages/home/index',
'pages/land/index',
'pages/swan/index.swan'
],
tabBar: {
list: [{
pagePath: 'pages/home/index',
text: 'API'
}, {
pagePath: 'pages/land/index',
text: 'Component'
}, {
pagePath: 'pages/swan/index.swan',
text: 'Swan'
}]
},
window: {
navigationBarBackgroundColor: '#3eaf7c',
navigationBarTextStyle: 'white'
},
networkTimeout: {
request: 30000
}
},
store,
onLaunch() {},
onShow() {}
};
```

完成,接下来就可以正常使用 vuex 了。

- vuex:暂不支持(开发中)
3 changes: 2 additions & 1 deletion packages/mars-build/package.json
Expand Up @@ -31,6 +31,7 @@
"through2": "^3.0.0",
"vinyl": "^2.2.0",
"vue-template-compiler": "2.5.21",
"vue-template-es2015-compiler": "^1.8.1"
"vue-template-es2015-compiler": "^1.8.1",
"webpack": "^4.30.0"
}
}
@@ -0,0 +1,59 @@
/**
* @file change import name to relative path
* @author meixuguang
*/

/* eslint-disable fecs-no-require */

const path = require('path');
const compileModules = require('./compileModules');
const moduleKeys = Object.keys(compileModules.modules);

module.exports = function ({types: t}) {
return {
visitor: {
ImportDeclaration(babelPath, state) {
const {filePath, cwd, usedModules} = 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, compileModules.modules[key].path);
let relativePath = path.relative(path.dirname(filePath), modulePath);
if (relativePath[0] !== '.') {
relativePath = './' + relativePath;
}
babelPath.node.source.value = name.replace(key, relativePath);

usedModules[name.replace(key, compileModules.modules[key].path)] = key;
}
},
CallExpression(nodePath, state) {
const {filePath, cwd, usedModules} = state.opts;
const node = nodePath.node;
const callee = node.callee;
const arg = node.arguments[0];

if (callee.type !== 'Identifier' || callee.name !== 'require' || !arg || arg.type !== 'StringLiteral') {
return;
}

const name = arg.value;

const key = moduleKeys.find(key => (new RegExp('^' + key + '(/.*)?$')).test(name));
if (key) {
const modulePath = path.join(cwd, compileModules.modules[key].path);
let relativePath = path.relative(path.dirname(filePath), modulePath);
if (relativePath[0] !== '.') {
relativePath = './' + relativePath;
}
nodePath.replaceWith(
t.callExpression(callee, [t.stringLiteral(name.replace(key, relativePath))])
);

usedModules[name.replace(key, compileModules.modules[key].path)] = key;
}
}
}
};
};
3 changes: 3 additions & 0 deletions packages/mars-build/src/compiler/file/base.js
Expand Up @@ -2,7 +2,9 @@
* @file base file compiler
* @author zhangwentao <winty2013@gmail.com>
*/

/* eslint-disable fecs-min-vars-per-destructure */
/* eslint-disable fecs-no-require */

const buildInProcessors = require('./processor');

Expand Down Expand Up @@ -54,6 +56,7 @@ function getFileCompiler(compile, config) {
// preprocessors
source = await process(source, getExtProcessors(preprocessors, lang));
// compile
options.path = file.path;
const result = await compile(source, options, fileOptions);
// postprocessors
let {code, ...rest} = result;
Expand Down
102 changes: 102 additions & 0 deletions packages/mars-build/src/compiler/file/compileModules.js
@@ -0,0 +1,102 @@
/**
* @file 编译外部依赖模块,原因:
* 1. 有些模块中有 process.env.NODE_ENV 判断。
* 2. 微信小程序不识别项目文件夹之外的依赖
* @author meixuguang
*/

/* eslint-disable fecs-no-require */
/* globals Set */

const fs = require('fs-extra');
const webpack = require('webpack');
const log = require('../../helper/log');
const {getPathToCWD} = require('../../helper/path');
const path = require('path');

const modules = {
'@marsjs/core': {
needCompile: false,
path: './mars-core'
},
'vuex': {
needCompile: true,
path: './mars_modules/vuex'
}
};

const inProcessingModules = new Set();

/**
* compile
*
* @param {string} val key
* @param {string} key key
* @param {string} destPath dest
* @return {Promise}
*/
function compile(val, key, destPath) {
if (!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', '');
}

if (fs.existsSync(path.resolve(destPath, modulePath)) || inProcessingModules.has(entry)) {
return Promise.resolve();
}

log.info('[compile:module]:', getPathToCWD(entry));

inProcessingModules.add(entry);
return new Promise((resolve, reject) => {
webpack({
entry: [entry],
output: {
path: destPath,
filename: modulePath,
libraryTarget: 'commonjs'
},
mode: process.env.NODE_ENV === 'production' ? 'production' : 'development'
}, (err, stats) => {
if (err) {
log.error(err.stack || err);
if (err.details) {
log.error(err.details);
}
return resolve();
}

const info = stats.toJson();

if (stats.hasErrors()) {
log.error(info.errors);
}

if (stats.hasWarnings()) {
log.warn(info.warnings);
}
inProcessingModules.delete(entry);
resolve();
// Done processing
});
});

}

module.exports = {
compile,
modules
};
33 changes: 31 additions & 2 deletions packages/mars-build/src/compiler/file/compiler.js
Expand Up @@ -2,7 +2,9 @@
* @file gulp plugin file compiler
* @author zhangwentao <winty2013@gmail.com>
*/

/* eslint-disable fecs-min-vars-per-destructure */
/* eslint-disable fecs-no-require */

const through = require('through2');
const gutil = require('gulp-util');
Expand All @@ -16,11 +18,20 @@ const {compile: compileStyle} = require('../style/style');
const {getFileCompiler} = require('./base');
const {isCSS, isJS, changeExt} = require('../../helper/path');
const log = require('../../helper/log');
const compileModules = require('./compileModules');

function compileJS(content, options) {
/**
* 编译 JS
*
* @param {string} content 文件内容
* @param {mars.options} options opt
* @return {babel.BabelFileResult}
*/
async function compileJS(content, options) {
const {
target
} = options;
const buildConfig = options._config;

content = content.replace(
/process\.env\.MARS_ENV/g,
Expand All @@ -30,12 +41,30 @@ function compileJS(content, options) {
JSON.stringify(process.env.NODE_ENV || 'development')
);

return transformSync(content, {
let usedModules = {};
let res = transformSync(content, {
plugins: [
[
path.resolve(__dirname, './babel-plugin-relative-import.js'),
{
filePath: options.path,
cwd: path.resolve(process.cwd(), './src'),
usedModules
}
],
'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);
}

return res;
}

async function compile(file, options) {
Expand Down