Skip to content

Commit 3087b96

Browse files
committed
feat(cli): support run with sfc
1 parent bbad49c commit 3087b96

File tree

10 files changed

+911
-3
lines changed

10 files changed

+911
-3
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,5 @@ user.config.js
5050
# lock
5151
yarn.lock
5252
package-lock.json
53+
54+
.temp

packages/cli/package.json

+42-1
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,55 @@
2323
},
2424
"homepage": "https://github.com/wya-team/vue-env#readme",
2525
"dependencies": {
26+
"@babel/core": "^7.11.6",
27+
"@babel/plugin-proposal-class-properties": "^7.10.4",
28+
"@babel/plugin-proposal-decorators": "^7.10.5",
29+
"@babel/plugin-proposal-export-default-from": "^7.10.4",
30+
"@babel/plugin-proposal-export-namespace-from": "^7.10.4",
31+
"@babel/plugin-proposal-function-bind": "^7.11.5",
32+
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
33+
"@babel/plugin-syntax-jsx": "^7.10.4",
34+
"@babel/plugin-transform-modules-commonjs": "^7.10.4",
35+
"@babel/plugin-transform-runtime": "^7.11.5",
36+
"@babel/preset-env": "^7.11.5",
37+
"@babel/runtime": "^7.11.2",
38+
"@wya/http": "^1.5.0-alpha.2",
39+
"@wya/ps": "^1.0.2",
40+
"@wya/qrcode": "^1.0.2",
41+
"@wya/sass": "^1.2.0",
42+
"@wya/socket": "^1.1.0",
2643
"@wya/toolkit-utils": "^1.0.0",
44+
"@wya/utils": "^1.6.2",
45+
"@wya/vc": "^2.0.0-alpha.80",
46+
"@wya/vc-loader": "^0.3.5",
47+
"@wya/vm": "^2.0.0-alpha.46",
48+
"babel-loader": "^8.1.0",
49+
"babel-plugin-syntax-jsx": "^6.18.0",
50+
"babel-plugin-transform-vue-jsx": "^3.7.0",
2751
"cac": "^6.5.6",
2852
"chalk": "^3.0.0",
2953
"chokidar": "^3.3.1",
54+
"css-loader": "^4.3.0",
3055
"del": "^5.1.0",
56+
"friendly-errors-webpack-plugin": "^1.7.0",
3157
"fs-extra": "^8.1.0",
58+
"html-loader": "^1.3.1",
59+
"html-webpack-plugin": "^4.5.0",
3260
"inquirer": "^7.0.6",
33-
"upath": "^1.2.0"
61+
"lodash": "^4.17.20",
62+
"node-sass": "^4.14.1",
63+
"sass-loader": "^10.0.2",
64+
"sass-resources-loader": "^2.1.1",
65+
"upath": "^1.2.0",
66+
"url-loader": "^4.1.0",
67+
"vue": "^2.6.12",
68+
"vue-loader": "^15.9.3",
69+
"vue-style-loader": "^4.1.2",
70+
"vue-template-compiler": "^2.6.12",
71+
"webpack": "^4.44.2",
72+
"webpack-cli": "^3.3.12",
73+
"webpack-dev-server": "^3.11.0",
74+
"webpack-merge": "^5.1.4"
3475
},
3576
"devDependencies": {
3677
"chai": "^4.2.0",

packages/cli/src/commands.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
const Run = require('./run');
22
const Add = require('./add');
33
const Init = require('./init');
4+
const SFC = require('./sfc');
45

56
exports.Run = Run;
67
exports.Add = Add;
7-
exports.Init = Init;
8+
exports.Init = Init;
9+
exports.SFC = SFC;

packages/cli/src/index.js

+12-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
const chalk = require('chalk');
22
const program = require('cac')();
33
const { resolve } = require('path');
4-
const { Run, Add, Init } = require('./commands');
4+
const { Run, Add, Init, SFC } = require('./commands');
55

66
const { log } = console;
77
program
@@ -64,6 +64,17 @@ program
6464
// TODO
6565
});
6666

67+
// Run sfc
68+
program
69+
.command('sfc [sourceDir]', 'sfc')
70+
.action((sourceDir = '.', commandOptions) => {
71+
let app = new SFC({
72+
sourceDir: resolve(sourceDir),
73+
...commandOptions
74+
});
75+
app.dev();
76+
});
77+
6778
// Run update|upgrade
6879
program
6980
.command('update [sourceDir]', 'update templates')

packages/cli/src/sfc/config.js

+194
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
const path = require('path');
2+
const fs = require('fs-extra');
3+
const HtmlWebpackPlugin = require('html-webpack-plugin');
4+
const webpack = require('webpack');
5+
const { merge } = require('webpack-merge');
6+
const VueLoaderPlugin = require('vue-loader/lib/plugin');
7+
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin');
8+
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
9+
10+
const { resolve } = path;
11+
const cwd = process.cwd();
12+
13+
const BASIC_NMS = [
14+
resolve(__dirname, '../node_modules'),
15+
resolve(cwd, './node_modules'),
16+
resolve(cwd, '../../node_modules')
17+
];
18+
const NMS = [
19+
...BASIC_NMS,
20+
// 增加编译速度
21+
...module.paths
22+
];
23+
24+
const resolvePackage = (source) => {
25+
let $path = NMS.find(i => fs.pathExistsSync(resolve(i, source)));
26+
27+
if (!$path) {
28+
throw new Error(`@wya/doc: 未找到${source}`);
29+
}
30+
31+
return resolve($path, source);
32+
};
33+
const resolveClient = (source) => {
34+
return resolve(__dirname, '../client', source || '');
35+
};
36+
37+
class Config {
38+
constructor(type, parent) {
39+
40+
this.$parent = parent;
41+
42+
this.result = type === 'webpack' || type === true
43+
? this.generateDefault()
44+
: this.generateServer();
45+
}
46+
47+
/**
48+
* 针对@wya/vc有做特殊处理
49+
*/
50+
generateDefault() {
51+
const { webpackAssist, tempDir } = this.$parent.$parent;
52+
const { port, host } = this.$parent;
53+
const { entry, htmls, openPage } = webpackAssist;
54+
55+
const exclude = new RegExp(`(${BASIC_NMS.join('|')})`);
56+
57+
let origin = `http://${host}:${port}`;
58+
let messages = [`Dev Server: ${origin}`];
59+
if (Object.keys(openPage).length > 0) {
60+
for (let item in openPage) {
61+
messages.push(`${item}: ${origin}${openPage[item]}`);
62+
}
63+
}
64+
65+
const defaultOptions = {
66+
mode: 'development',
67+
devtool: 'cheap-module-eval-source-map',
68+
entry,
69+
output: {
70+
path: resolve(__dirname, '../dist'),
71+
filename: `js/[name].bundle.js`,
72+
chunkFilename: `js/[name].chunk.js`,
73+
sourceMapFilename: `js/[name].bundle.map`,
74+
publicPath: '/',
75+
},
76+
resolve: {
77+
modules: NMS,
78+
extensions: ['.vue', '.js', '.json', '.md', '.css', '.scss'],
79+
symlinks: true,
80+
alias: {
81+
'vue$': resolvePackage('vue/dist/vue.esm.js'),
82+
'babel-runtime': resolvePackage('@babel/runtime')
83+
}
84+
},
85+
module: {
86+
rules: [
87+
{
88+
test: /\.js$/,
89+
exclude,
90+
use: {
91+
loader: resolvePackage('babel-loader'),
92+
options: {
93+
babelrc: false,
94+
configFile: false,
95+
compact: false,
96+
cacheDirectory: true,
97+
presets: [
98+
resolvePackage('@babel/preset-env')
99+
],
100+
plugins: [
101+
resolvePackage('@babel/plugin-proposal-export-namespace-from'),
102+
resolvePackage('@babel/plugin-proposal-export-default-from'),
103+
resolvePackage('@babel/plugin-proposal-function-bind'),
104+
resolvePackage('@babel/plugin-syntax-dynamic-import'),
105+
resolvePackage('@babel/plugin-transform-modules-commonjs'),
106+
resolvePackage('@babel/plugin-syntax-jsx'),
107+
resolvePackage("@babel/plugin-transform-runtime"),
108+
resolvePackage('babel-plugin-transform-vue-jsx'),
109+
[
110+
resolvePackage('@babel/plugin-proposal-decorators'),
111+
{
112+
"legacy": true
113+
}
114+
],
115+
[
116+
resolvePackage('@babel/plugin-proposal-class-properties'),
117+
{
118+
"loose": true
119+
}
120+
]
121+
]
122+
}
123+
}
124+
},
125+
{
126+
test: /\.vue$/,
127+
exclude,
128+
use: [
129+
{
130+
loader: resolvePackage('vue-loader'),
131+
},
132+
{
133+
loader: resolvePackage('@wya/vc-loader'),
134+
}
135+
]
136+
},
137+
{
138+
test: /\.(scss|css)$/,
139+
use: [
140+
resolvePackage('vue-style-loader'),
141+
resolvePackage('css-loader'),
142+
resolvePackage('sass-loader'),
143+
{
144+
loader: resolvePackage('sass-resources-loader'),
145+
options: {
146+
resources: [
147+
resolvePackage("@wya/sass/lib/mixins/bem.scss")
148+
]
149+
}
150+
}
151+
]
152+
},
153+
{
154+
test: /\.(png|jpg|gif|eot|ttf|woff|woff2|svg)$/,
155+
loader: resolvePackage('url-loader')
156+
}
157+
]
158+
},
159+
plugins: [
160+
new VueLoaderPlugin(),
161+
new FriendlyErrorsPlugin({
162+
compilationSuccessInfo: {
163+
messages,
164+
notes: [`Success!`]
165+
}
166+
}),
167+
...htmls
168+
]
169+
};
170+
171+
return merge(defaultOptions);
172+
}
173+
174+
generateServer() {
175+
const { port, host } = this.$parent;
176+
177+
return merge(
178+
{
179+
hot: true,
180+
quiet: true,
181+
historyApiFallback: true,
182+
publicPath: '/',
183+
port,
184+
host
185+
}
186+
);
187+
}
188+
189+
}
190+
module.exports = {
191+
get(type = 'webpack', parent) {
192+
return new Config(type, parent).result;
193+
}
194+
};

packages/cli/src/sfc/dev.js

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
const { EventEmitter } = require('events');
2+
const path = require('path');
3+
const fs = require('fs-extra');
4+
const webpack = require('webpack');
5+
const portfinder = require('portfinder');
6+
const chokidar = require('chokidar');
7+
8+
const WebpackDevServer = require('webpack-dev-server');
9+
const Config = require('./config');
10+
const { localhost } = require('./utils');
11+
12+
class DevProcess extends EventEmitter {
13+
constructor(parent) {
14+
super();
15+
this.$parent = parent;
16+
this.port = 8080;
17+
this.host = localhost;
18+
}
19+
20+
/**
21+
* 为启动dev服务器准备必要的数据
22+
*/
23+
async process() {
24+
await this.resolvePort();
25+
await this.resolveHost();
26+
27+
return this;
28+
}
29+
30+
async resolvePort() {
31+
let port = this.$parent.options.port || this.port;
32+
33+
portfinder.basePort = parseInt(port, 10);
34+
port = await portfinder.getPortPromise();
35+
36+
this.port = port;
37+
}
38+
39+
async resolveHost() {
40+
this.host = this.$parent.options.host || this.host;
41+
}
42+
43+
/**
44+
* Create dev server
45+
* https://github.com/webpack/webpack-dev-server/blob/master/examples/api/simple/server.js
46+
* https://webpack.js.org/guides/development/#using-webpack-dev-middleware
47+
* @returns {module.DevProcess}
48+
*/
49+
createServer() {
50+
const compiler = webpack(Config.get('webpack', this));
51+
let server = new WebpackDevServer(
52+
compiler,
53+
Config.get('server', this)
54+
);
55+
56+
this.server = server;
57+
return this;
58+
}
59+
60+
listen(callback) {
61+
this.server.listen(this.port, this.host, (err) => {
62+
if (typeof callback === 'function') {
63+
callback(err);
64+
}
65+
});
66+
return this;
67+
}
68+
}
69+
70+
module.exports = DevProcess;

0 commit comments

Comments
 (0)