@xujingquan/elpis 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.browserslistrc +3 -0
- package/.eslintignore +4 -0
- package/.eslintrc +63 -0
- package/.husky/commit-msg +1 -0
- package/.husky/pre-commit +1 -0
- package/.prettierignore +16 -0
- package/.prettierrc +10 -0
- package/README.md +248 -0
- package/app/controller/base.js +41 -0
- package/app/controller/project.js +75 -0
- package/app/controller/view.js +28 -0
- package/app/extend/logger.js +39 -0
- package/app/middleware/api-params-verify.js +90 -0
- package/app/middleware/api-sign-veriyf.js +47 -0
- package/app/middleware/error-handler.js +33 -0
- package/app/middleware/project-handler.js +30 -0
- package/app/middleware.js +45 -0
- package/app/pages/asserts/custom.css +13 -0
- package/app/pages/boot.js +56 -0
- package/app/pages/common/api/business-api.js +19 -0
- package/app/pages/common/api/project-api.js +27 -0
- package/app/pages/common/request.js +119 -0
- package/app/pages/common/utils.js +2 -0
- package/app/pages/dashboard/complex-view/header-view/complex-view/sub-menu/sub-menu.vue +20 -0
- package/app/pages/dashboard/complex-view/header-view/header-view.vue +116 -0
- package/app/pages/dashboard/complex-view/iframe-view/iframe-view.vue +44 -0
- package/app/pages/dashboard/complex-view/schema-view/complex-view/search-panel/search-panel.vue +37 -0
- package/app/pages/dashboard/complex-view/schema-view/complex-view/table-panel/table-panel.vue +122 -0
- package/app/pages/dashboard/complex-view/schema-view/components/component-config.js +23 -0
- package/app/pages/dashboard/complex-view/schema-view/components/create-form/create-form.vue +86 -0
- package/app/pages/dashboard/complex-view/schema-view/components/detail-panel/detail-panel.vue +82 -0
- package/app/pages/dashboard/complex-view/schema-view/components/edit-form/edit-form.vue +115 -0
- package/app/pages/dashboard/complex-view/schema-view/hook/schema.js +135 -0
- package/app/pages/dashboard/complex-view/schema-view/schema-view.vue +93 -0
- package/app/pages/dashboard/complex-view/sider-view/complex-view/sub-menu/sub-menu.vue +21 -0
- package/app/pages/dashboard/complex-view/sider-view/sider-view.vue +115 -0
- package/app/pages/dashboard/dashboard.vue +93 -0
- package/app/pages/dashboard/entry.dashboard.js +45 -0
- package/app/pages/store/index.js +4 -0
- package/app/pages/store/menu.js +61 -0
- package/app/pages/store/project.js +17 -0
- package/app/pages/widgets/header-container/asserts/avatar.png +0 -0
- package/app/pages/widgets/header-container/asserts/logo.png +0 -0
- package/app/pages/widgets/header-container/header-container.vue +111 -0
- package/app/pages/widgets/schema-form/complex-view/input/input.vue +141 -0
- package/app/pages/widgets/schema-form/complex-view/input-number/input-number.vue +142 -0
- package/app/pages/widgets/schema-form/complex-view/select/select.vue +119 -0
- package/app/pages/widgets/schema-form/form-item-config.js +23 -0
- package/app/pages/widgets/schema-form/schema-form.vue +130 -0
- package/app/pages/widgets/schema-search-bar/complex-view/date-range/date-range.vue +50 -0
- package/app/pages/widgets/schema-search-bar/complex-view/dynamic-select/dynamic-select.vue +62 -0
- package/app/pages/widgets/schema-search-bar/complex-view/input/input.vue +40 -0
- package/app/pages/widgets/schema-search-bar/complex-view/select/select.vue +48 -0
- package/app/pages/widgets/schema-search-bar/schema-search-bar.vue +121 -0
- package/app/pages/widgets/schema-search-bar/search-item-config.js +27 -0
- package/app/pages/widgets/schema-table/schema-table.vue +243 -0
- package/app/pages/widgets/sider-container/sider-container.vue +26 -0
- package/app/public/static/logo.png +0 -0
- package/app/public/static/md5.js +950 -0
- package/app/public/static/normalize.css +267 -0
- package/app/router/project.js +11 -0
- package/app/router/view.js +13 -0
- package/app/router-schema/project.js +33 -0
- package/app/service/base.js +14 -0
- package/app/service/project.js +43 -0
- package/app/view/entry.tpl +27 -0
- package/app/webpack/config/utils.js +49 -0
- package/app/webpack/config/webpack-dev.js +55 -0
- package/app/webpack/config/webpack-prod.js +192 -0
- package/app/webpack/config/webpack.base.js +273 -0
- package/app/webpack/dev.js +60 -0
- package/app/webpack/libs/blank.js +1 -0
- package/app/webpack/prod.js +27 -0
- package/babel.config.js +15 -0
- package/commitlint.config.js +3 -0
- package/config/config.default.js +4 -0
- package/elpis-core/env.js +20 -0
- package/elpis-core/index.js +86 -0
- package/elpis-core/loader/config.js +54 -0
- package/elpis-core/loader/controller.js +69 -0
- package/elpis-core/loader/extend.js +57 -0
- package/elpis-core/loader/middleware.js +66 -0
- package/elpis-core/loader/router-schema.js +49 -0
- package/elpis-core/loader/router.js +50 -0
- package/elpis-core/loader/service.js +69 -0
- package/index.js +47 -0
- package/jsconfig.json +19 -0
- package/model/index.js +103 -0
- package/package.json +105 -0
- package/test/controller/project.test.js +200 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const glob = require('glob');
|
|
3
|
+
const merge = require('webpack-merge');
|
|
4
|
+
|
|
5
|
+
// Node 环境下为依赖提供 crypto.getRandomValues
|
|
6
|
+
const { webcrypto } = require('crypto');
|
|
7
|
+
global.crypto = webcrypto;
|
|
8
|
+
|
|
9
|
+
const os = require('os');
|
|
10
|
+
// const HappyPack = require('happypack'); // 多线程打包工具
|
|
11
|
+
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
|
12
|
+
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
|
|
13
|
+
const HtmlWebpackInjectAttributesPlugin = require('html-webpack-inject-attributes-plugin');
|
|
14
|
+
const TerserWebpackPlugin = require('terser-webpack-plugin');
|
|
15
|
+
const CompressionPlugin = require('compression-webpack-plugin');
|
|
16
|
+
const { PurgeCSSPlugin } = require('purgecss-webpack-plugin');
|
|
17
|
+
|
|
18
|
+
const { cssCollectSafelist } = require('./utils');
|
|
19
|
+
|
|
20
|
+
// 多线程 build 设置
|
|
21
|
+
// const happypackCommonConfig = {
|
|
22
|
+
// debug: false,
|
|
23
|
+
// threadPool: HappyPack.ThreadPool({
|
|
24
|
+
// // 某些受限运行环境(例如沙箱)可能拿不到 CPU 信息,导致 length 为 0
|
|
25
|
+
// size: Math.max(1, os.cpus().length || 0)
|
|
26
|
+
// })
|
|
27
|
+
// };
|
|
28
|
+
const threadLoaderConfig = {
|
|
29
|
+
workers: Math.max(1, os.cpus().length || 0),
|
|
30
|
+
workerParallelJobs: 50,
|
|
31
|
+
workerNodeArgs: ['--max-old-space-size=1024'],
|
|
32
|
+
poolRespawn: false,
|
|
33
|
+
poolTimeout: 2000,
|
|
34
|
+
poolParallelJobs: 50,
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// 基础配置
|
|
38
|
+
const baseConfig = require('./webpack.base');
|
|
39
|
+
|
|
40
|
+
// 生产环境配置
|
|
41
|
+
const webpackConfig = merge(baseConfig, {
|
|
42
|
+
mode: 'production',
|
|
43
|
+
devtool: 'source-map',
|
|
44
|
+
// 生产环境的 output 配置
|
|
45
|
+
output: {
|
|
46
|
+
filename: 'js/[name]_[chunkhash:8].bundle.js',
|
|
47
|
+
path: path.join(process.cwd(), './app/public/dist/prod/'),
|
|
48
|
+
publicPath: '/dist/prod/',
|
|
49
|
+
crossOriginLoading: 'anonymous', // 允许跨域
|
|
50
|
+
clean: true, // 和 clean-webpack-plugin 插件一样
|
|
51
|
+
},
|
|
52
|
+
module: {
|
|
53
|
+
// 使用 require.resolve 告诉 webpack loader 使用 elpis 中安装的插件
|
|
54
|
+
rules: [
|
|
55
|
+
// {
|
|
56
|
+
// // 压缩 css 文件开启多线程
|
|
57
|
+
// test: /\.css$/i,
|
|
58
|
+
// use: [MiniCssExtractPlugin.loader, 'happypack/loader?id=css']
|
|
59
|
+
// },
|
|
60
|
+
// {
|
|
61
|
+
// test: /\.js$/i,
|
|
62
|
+
// // 只处理这部分代码
|
|
63
|
+
// include: [path.resolve(process.cwd(), './app/pages')],
|
|
64
|
+
// use: ['happypack/loader?id=js']
|
|
65
|
+
// }
|
|
66
|
+
{
|
|
67
|
+
test: /\.css$/i,
|
|
68
|
+
use: [
|
|
69
|
+
MiniCssExtractPlugin.loader,
|
|
70
|
+
{
|
|
71
|
+
loader: require.resolve('thread-loader'),
|
|
72
|
+
options: threadLoaderConfig,
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
loader: require.resolve('css-loader'),
|
|
76
|
+
options: {
|
|
77
|
+
importLoaders: 2,
|
|
78
|
+
esModule: false,
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
loader: require.resolve('postcss-loader'),
|
|
83
|
+
options: {
|
|
84
|
+
postcssOptions: {
|
|
85
|
+
plugins: [['postcss-preset-env', {}]],
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
],
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
test: /\.js$/i,
|
|
93
|
+
include: [
|
|
94
|
+
// 处理 elips 目录
|
|
95
|
+
path.resolve(__dirname, '../../pages'),
|
|
96
|
+
// 处理 业务 目录
|
|
97
|
+
path.resolve(process.cwd(), '.app/pages'),
|
|
98
|
+
],
|
|
99
|
+
// js 文件使用 babel-loader 并且添加 babel.config.js 会根据这个文件去做兼容处理
|
|
100
|
+
use: [
|
|
101
|
+
{
|
|
102
|
+
loader: require.resolve('thread-loader'),
|
|
103
|
+
options: threadLoaderConfig,
|
|
104
|
+
},
|
|
105
|
+
require.resolve('babel-loader'),
|
|
106
|
+
],
|
|
107
|
+
},
|
|
108
|
+
],
|
|
109
|
+
},
|
|
110
|
+
// webpack 不会有大量 hints 信息,默认为 warning
|
|
111
|
+
performance: {
|
|
112
|
+
hints: false,
|
|
113
|
+
},
|
|
114
|
+
plugins: [
|
|
115
|
+
// 01.每次 build 前,清空 public/dist 目录
|
|
116
|
+
// new html-webpack-plugin
|
|
117
|
+
// 配置 output.clean 无需使用html-webpack-plugin
|
|
118
|
+
// --
|
|
119
|
+
// 02.提取 css 的公共部分。有效利用缓存(非公共部分使用 inline)
|
|
120
|
+
new MiniCssExtractPlugin({
|
|
121
|
+
chunkFilename: 'css/[name]_[contenthash:8].bundle.css',
|
|
122
|
+
}),
|
|
123
|
+
// 03.css 树摇
|
|
124
|
+
new PurgeCSSPlugin({
|
|
125
|
+
paths: glob.sync(`${path.join(__dirname, '../../pages')}/**/*`, {
|
|
126
|
+
nodir: true,
|
|
127
|
+
}),
|
|
128
|
+
safelist: cssCollectSafelist, // 安全列表
|
|
129
|
+
}),
|
|
130
|
+
// 04.优化并压缩 css 资源
|
|
131
|
+
new CssMinimizerPlugin(),
|
|
132
|
+
// 05.多线程打包 js 加速打包速度
|
|
133
|
+
// new HappyPack({
|
|
134
|
+
// ...happypackCommonConfig,
|
|
135
|
+
// id: 'js',
|
|
136
|
+
// loaders: [
|
|
137
|
+
// `babel-loader?${JSON.stringify({
|
|
138
|
+
// presets: ['@babel/preset-env'],
|
|
139
|
+
// plugins: ['@babel/plugin-transform-runtime']
|
|
140
|
+
// })}`
|
|
141
|
+
// ]
|
|
142
|
+
// }),
|
|
143
|
+
// 06.多线程打包 css 加快打包速度
|
|
144
|
+
// new HappyPack({
|
|
145
|
+
// ...happypackCommonConfig,
|
|
146
|
+
// id: 'css',
|
|
147
|
+
// loaders: [
|
|
148
|
+
// {
|
|
149
|
+
// path: 'css-loader',
|
|
150
|
+
// options: {
|
|
151
|
+
// importLoaders: 2
|
|
152
|
+
// }
|
|
153
|
+
// }
|
|
154
|
+
// ]
|
|
155
|
+
// }),
|
|
156
|
+
// 07.浏览器在请求资源时不发送用户的身份凭证
|
|
157
|
+
new HtmlWebpackInjectAttributesPlugin({
|
|
158
|
+
crossorigin: 'anonymous',
|
|
159
|
+
}),
|
|
160
|
+
// 08 添加资源压缩
|
|
161
|
+
new CompressionPlugin({
|
|
162
|
+
test: /\.(css|js)$/, // 只匹配css、js 文件
|
|
163
|
+
minRatio: 0.8, // 压缩比例
|
|
164
|
+
threshold: 0, // 体积大于 开始压缩
|
|
165
|
+
algorithm: 'gzip', // 压缩算法
|
|
166
|
+
}),
|
|
167
|
+
// 09.打包时间和内容分析
|
|
168
|
+
// new BundleAnalyzerPlugin()
|
|
169
|
+
],
|
|
170
|
+
optimization: {
|
|
171
|
+
usedExports: true, // 标记不被使用的代码,后续需要配置 minimize 和 terser-webpack-plugin 去做代码剥离不进行打包
|
|
172
|
+
minimize: true, // 需要使用 terser-webpack-plugin 就需要设置为true
|
|
173
|
+
minimizer: [
|
|
174
|
+
// 01.使用 TerserWebpackPlugin 的并发和缓存,提升压缩阶段的性能
|
|
175
|
+
new TerserWebpackPlugin({
|
|
176
|
+
// extractComments: true, // 启用/禁用剥离注释功能
|
|
177
|
+
// cache: true, // 启用缓存来构建过程
|
|
178
|
+
parallel: true, // 利用多核 CPU 的优势来加快压缩速度
|
|
179
|
+
terserOptions: {
|
|
180
|
+
ecma: 2020,
|
|
181
|
+
// 02.清除 console,log
|
|
182
|
+
compress: {
|
|
183
|
+
// 移除所有 console.* 语句
|
|
184
|
+
drop_console: true,
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
}),
|
|
188
|
+
],
|
|
189
|
+
},
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
module.exports = webpackConfig;
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const webpack = require('webpack');
|
|
3
|
+
const glob = require('glob');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
|
|
6
|
+
const { VueLoaderPlugin } = require('vue-loader');
|
|
7
|
+
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
|
8
|
+
const merge = require('webpack-merge');
|
|
9
|
+
|
|
10
|
+
// 动态构造 elipsPageEntries(入口文件) & elipsHtmlWebpackPluginList(渲染页面)
|
|
11
|
+
const elipsPageEntries = {};
|
|
12
|
+
const elipsHtmlWebpackPluginList = [];
|
|
13
|
+
// 获取 elips/app/pages 目录下的所有入口文件 (enter.xx.js)
|
|
14
|
+
const elipsEntryList = path.resolve(__dirname, '../../pages/**/entry.*.js');
|
|
15
|
+
glob.sync(elipsEntryList).forEach((file) => {
|
|
16
|
+
haneleFile(file, elipsPageEntries, elipsHtmlWebpackPluginList);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
// 动态构造 businessPageEntries(入口文件) & businessHtmlWebpackPluginList(渲染页面)
|
|
20
|
+
const businessPageEntries = {};
|
|
21
|
+
const businessHtmlWebpackPluginList = [];
|
|
22
|
+
// 获取 business/app/pages 目录下的所有入口文件 (enter.xx.js)
|
|
23
|
+
const businessEntryList = path.resolve(process.cwd(), './app/pages/**/entry.*.js');
|
|
24
|
+
glob.sync(businessEntryList).forEach((file) => {
|
|
25
|
+
haneleFile(file, businessPageEntries, businessHtmlWebpackPluginList);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// 构造相关 webpack 处理的相关数据结构
|
|
29
|
+
function haneleFile(file, entries = {}, htmlWebpackPluginList = []) {
|
|
30
|
+
// basename 获取路径文件的基础名称 ./app/pages/entry.page1.js => entry.page1
|
|
31
|
+
const entryName = path.basename(file, '.js');
|
|
32
|
+
// 构造 entry
|
|
33
|
+
entries[entryName] = file;
|
|
34
|
+
// 构造最终渲染页面文件
|
|
35
|
+
htmlWebpackPluginList.push(
|
|
36
|
+
new HtmlWebpackPlugin({
|
|
37
|
+
// 最终模版输出路径
|
|
38
|
+
filename: path.resolve(process.cwd(), './app/public/dist/', `${entryName}.tpl`),
|
|
39
|
+
// 使用模版路径
|
|
40
|
+
template: path.resolve(__dirname, '../../view/entry.tpl'),
|
|
41
|
+
// 摇注入的代码块(只会把 entry.page2 相关的资源(以及它依赖的运行时代码/分包,如果配置了 splitChunks 等)注入到这个 tpl 里)
|
|
42
|
+
chunks: [entryName],
|
|
43
|
+
})
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// 加载业务 webpack 配置, merge 到 elips 中
|
|
48
|
+
let businessWebpackConfig = {};
|
|
49
|
+
try {
|
|
50
|
+
businessWebpackConfig = require(`${process.cwd()}/app/webpack.config.js`);
|
|
51
|
+
} catch (e) {}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* webpack 基础配置
|
|
55
|
+
*/
|
|
56
|
+
module.exports = merge(businessWebpackConfig, {
|
|
57
|
+
// 入口配置
|
|
58
|
+
entry: Object.assign({}, elipsPageEntries, businessPageEntries), // 框架入口 & 业务入口
|
|
59
|
+
// loader 配置,模块解析配置
|
|
60
|
+
module: {
|
|
61
|
+
// 使用 require.resolve 告诉 webpack loader 使用 elpis 中安装的插件
|
|
62
|
+
rules: [
|
|
63
|
+
// vue 文件使用 vue-loader
|
|
64
|
+
{
|
|
65
|
+
test: /\.vue$/i,
|
|
66
|
+
use: [require.resolve('vue-loader')],
|
|
67
|
+
},
|
|
68
|
+
// js 文件使用 babel-loader 并且添加 babel.config.js 会根据这个文件去做兼容处理
|
|
69
|
+
{
|
|
70
|
+
test: /\.js$/i,
|
|
71
|
+
// 只处理这部分代码
|
|
72
|
+
include: [
|
|
73
|
+
// 处理 elips 目录
|
|
74
|
+
path.resolve(__dirname, '../../pages'),
|
|
75
|
+
// 处理 业务 目录
|
|
76
|
+
path.resolve(process.cwd(), '.app/pages'),
|
|
77
|
+
],
|
|
78
|
+
|
|
79
|
+
use: [require.resolve('babel-loader')],
|
|
80
|
+
},
|
|
81
|
+
// 图片资源文件使用webpack 提供的资源模块替换loader
|
|
82
|
+
{
|
|
83
|
+
test: /\.(png|jpe?g|gif)$/i,
|
|
84
|
+
type: 'asset',
|
|
85
|
+
// generator: {
|
|
86
|
+
// filename: 'images/[name].[hash:4][ext]'
|
|
87
|
+
// },
|
|
88
|
+
parser: {
|
|
89
|
+
dataUrlCondition: {
|
|
90
|
+
maxSize: 4 * 1024, // 4kb
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
// css文件
|
|
95
|
+
{
|
|
96
|
+
test: /\.css$/i,
|
|
97
|
+
use: [
|
|
98
|
+
require.resolve('style-loader'),
|
|
99
|
+
{
|
|
100
|
+
loader: require.resolve('css-loader'),
|
|
101
|
+
options: {
|
|
102
|
+
importLoaders: 2,
|
|
103
|
+
esModule: false,
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
loader: require.resolve('postcss-loader'), // 用于浏览器兼容
|
|
108
|
+
options: {
|
|
109
|
+
postcssOptions: {
|
|
110
|
+
plugins: [['postcss-preset-env', {}]],
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
],
|
|
115
|
+
},
|
|
116
|
+
// less 文件
|
|
117
|
+
{
|
|
118
|
+
test: /\.less$/i,
|
|
119
|
+
use: [
|
|
120
|
+
require.resolve('style-loader'),
|
|
121
|
+
require.resolve('css-loader'),
|
|
122
|
+
require.resolve('less-loader'),
|
|
123
|
+
],
|
|
124
|
+
},
|
|
125
|
+
// 字体文件
|
|
126
|
+
{
|
|
127
|
+
test: /\.(woff|woff2|eot|ttf|otf|svg)$/i,
|
|
128
|
+
type: 'asset/resource',
|
|
129
|
+
// generator: {
|
|
130
|
+
// filename: 'font/[name].[hash:3][ext]'
|
|
131
|
+
// }
|
|
132
|
+
},
|
|
133
|
+
],
|
|
134
|
+
},
|
|
135
|
+
// 打包输出路径
|
|
136
|
+
// output: {},
|
|
137
|
+
// 模块解析,例如alias,告诉 webpack如何解析到具体路径
|
|
138
|
+
resolve: {
|
|
139
|
+
alias: (() => {
|
|
140
|
+
const aliasMap = {};
|
|
141
|
+
const blankModulePath = path.resolve(__dirname, '..libs/blank.js');
|
|
142
|
+
|
|
143
|
+
// 01.dashboard 路由扩展配置
|
|
144
|
+
const businessDashboardRoutreConfig = path.resolve(
|
|
145
|
+
process.cwd(),
|
|
146
|
+
'./app/pages/dashboard/router.js'
|
|
147
|
+
);
|
|
148
|
+
aliasMap['$businessDashboardRoutreConfig'] = fs.existsSync(businessDashboardRoutreConfig)
|
|
149
|
+
? businessDashboardRoutreConfig
|
|
150
|
+
: blankModulePath;
|
|
151
|
+
|
|
152
|
+
// 02.schema-view component 扩展配置
|
|
153
|
+
const businessComponentConfig = path.resolve(
|
|
154
|
+
process.cwd(),
|
|
155
|
+
'./app/pages/dashboard/complex-view/schema-view/components/component-config.js'
|
|
156
|
+
);
|
|
157
|
+
aliasMap['$businessComponentConfig'] = fs.existsSync(businessComponentConfig)
|
|
158
|
+
? businessComponentConfig
|
|
159
|
+
: blankModulePath;
|
|
160
|
+
|
|
161
|
+
// 03.schema-form 扩展配置
|
|
162
|
+
const businessFormItemConfig = path.resolve(
|
|
163
|
+
process.cwd(),
|
|
164
|
+
'./app/pages/widgets/schema-form/form-item-config.js'
|
|
165
|
+
);
|
|
166
|
+
aliasMap['$businessFormItemConfig'] = fs.existsSync(businessFormItemConfig)
|
|
167
|
+
? businessFormItemConfig
|
|
168
|
+
: blankModulePath;
|
|
169
|
+
|
|
170
|
+
// 04 schema-search-bar 扩展配置
|
|
171
|
+
const businessSearchItemConfig = path.resolve(
|
|
172
|
+
process.cwd(),
|
|
173
|
+
'./app/pages/widgets/schema-search-bar/search-item-config.js'
|
|
174
|
+
);
|
|
175
|
+
aliasMap['$businessSearchItemConfig'] = fs.existsSync(businessSearchItemConfig)
|
|
176
|
+
? businessSearchItemConfig
|
|
177
|
+
: blankModulePath;
|
|
178
|
+
|
|
179
|
+
return {
|
|
180
|
+
vue: require.resolve('vue'), // 使用 require.resolve 告诉 webpack 去这里找
|
|
181
|
+
$elpisPages: path.resolve(__dirname, '../../pages'),
|
|
182
|
+
$elpisCommon: path.resolve(__dirname, '../../pages/common'),
|
|
183
|
+
$elpisUtils: path.resolve(__dirname, '../../pages/common/utils'),
|
|
184
|
+
$elpisWidgets: path.resolve(__dirname, '../../pages/widgets'),
|
|
185
|
+
$elpisHeaderContainer: path.resolve(
|
|
186
|
+
__dirname,
|
|
187
|
+
'../../pages/widgets/header-container/header-container.vue'
|
|
188
|
+
),
|
|
189
|
+
$elpisSiderContainer: path.resolve(
|
|
190
|
+
__dirname,
|
|
191
|
+
'../../pages/widgets/sider-container/sider-container.vue'
|
|
192
|
+
),
|
|
193
|
+
$elpisSchemaTable: path.resolve(
|
|
194
|
+
__dirname,
|
|
195
|
+
'../../pages/widgets/schema-table/schema-table.vue'
|
|
196
|
+
),
|
|
197
|
+
$elpisSchemaForm: path.resolve(
|
|
198
|
+
__dirname,
|
|
199
|
+
'../../pages/widgets/schema-form/schema-form.vue'
|
|
200
|
+
),
|
|
201
|
+
$elpisSchemaSearchBar: path.resolve(
|
|
202
|
+
__dirname,
|
|
203
|
+
'../../pages/widgets/schema-search-bar/schema-search-bar.vue'
|
|
204
|
+
),
|
|
205
|
+
$elpisStore: path.resolve(__dirname, '../../pages/store'),
|
|
206
|
+
$elpisBoot: path.resolve(__dirname, '../../pages/boot.js'), // vue 启动文件暴露给外部使用,用来创建页面
|
|
207
|
+
...aliasMap,
|
|
208
|
+
};
|
|
209
|
+
})(), // 配置路径别名
|
|
210
|
+
extensions: ['.js', '.vue', '.less', '.css', '...'], // 用户引入文件可以不带后缀
|
|
211
|
+
},
|
|
212
|
+
// 配置 webpack 插件
|
|
213
|
+
plugins: [
|
|
214
|
+
// 处理 . vue 文件。这个插件是必须的
|
|
215
|
+
// 它的职能是将你定义过的其他规则复制并应用到 .vue 文件里
|
|
216
|
+
// 例如,如果有一条匹配规则 /\.js$/ 的规则,那么它会应用到 .vue 文件中的 <script></script> 中
|
|
217
|
+
new VueLoaderPlugin(),
|
|
218
|
+
// 把第三方库暴露到 window context 下
|
|
219
|
+
new webpack.ProvidePlugin({
|
|
220
|
+
Vue: 'vue',
|
|
221
|
+
axios: 'axios',
|
|
222
|
+
_: 'lodash',
|
|
223
|
+
}),
|
|
224
|
+
// 定义全局常量
|
|
225
|
+
new webpack.DefinePlugin({
|
|
226
|
+
__VUE_OPTIONS_API__: 'true', // 支持 vue 解析 options api
|
|
227
|
+
__VUE_PROD_DEVTOOLS__: 'false', // 禁用 vue 调试工具
|
|
228
|
+
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: 'false', // 禁用生产环境显示 '水合' 信息
|
|
229
|
+
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'),
|
|
230
|
+
}),
|
|
231
|
+
// 构造最终渲染的页面模版
|
|
232
|
+
...elipsHtmlWebpackPluginList,
|
|
233
|
+
...businessHtmlWebpackPluginList,
|
|
234
|
+
],
|
|
235
|
+
// 配置打包输出优化(代码分割、模块合并、缓存、树摇(TreeShaing)、压缩等优化)
|
|
236
|
+
optimization: {
|
|
237
|
+
runtimeChunk: true,
|
|
238
|
+
/**
|
|
239
|
+
* 把 js 文件打包分成三种类型
|
|
240
|
+
* 01. vendor: 第三方 lib 库,基本不会改动,除非依赖版本升级。
|
|
241
|
+
* 02. common: 业务组件代码的公共部分抽取出来,改动较少。
|
|
242
|
+
* 03. entry.{page}: 不用页面 entry 里的业务组件代码的差异部分,会经常改动。
|
|
243
|
+
* 目的: 把改动和引用频率不一样的 js 区分出来,以达到更好利用浏览器缓存的效果。
|
|
244
|
+
*/
|
|
245
|
+
splitChunks: {
|
|
246
|
+
chunks: 'all', // all(全部代码)、async(异步代码)、initial(同步代码),可以使用这些chunk进行优化
|
|
247
|
+
maxAsyncRequests: 10, // 按需加载时的最大并行请求数。
|
|
248
|
+
maxInitialRequests: 10, // 入口点的最大并行请求数。
|
|
249
|
+
// 缓存组可以继承和/或覆盖来自 splitChunks.* 的任何选项
|
|
250
|
+
cacheGroups: {
|
|
251
|
+
// key 值可以按照自己规则去起名,例如现在的 vendor 、common
|
|
252
|
+
// 第三方依赖库
|
|
253
|
+
vendor: {
|
|
254
|
+
test: /[\\/]node_modules[\\/]/, // 路径或者文件名称
|
|
255
|
+
name: 'vendor', // 模块名称
|
|
256
|
+
// filename: 'js/[id]_vendor.js', // 输出的文件名称
|
|
257
|
+
priority: 0, // 优先级,值越大优先级就高
|
|
258
|
+
enforce: true, // 是否强制执行
|
|
259
|
+
reuseExistingChunk: true, // 复用已有的公共模块
|
|
260
|
+
},
|
|
261
|
+
// 公共模块
|
|
262
|
+
common: {
|
|
263
|
+
test: /[\\/]common|widgets[\\/]/, // 只处理这些文件,不影响路由的懒加载
|
|
264
|
+
name: 'common',
|
|
265
|
+
minChunks: 2, // 被引入的次数超过 2 次的,即视为公共模块
|
|
266
|
+
minSize: 1, // 最小分割文件大小、根据自己的文件大小去分配(目前 1 byte)实际不会填写这么小的值
|
|
267
|
+
priority: -10, // 优先级,值越大优先级就高
|
|
268
|
+
reuseExistingChunk: true, // 复用已有的公共模块
|
|
269
|
+
},
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
},
|
|
273
|
+
});
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* webpack dev 启动文件
|
|
3
|
+
* */
|
|
4
|
+
const express = require('express');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const webpack = require('webpack');
|
|
7
|
+
const devMiddleware = require('webpack-dev-middleware');
|
|
8
|
+
const hotMiddleware = require('webpack-hot-middleware');
|
|
9
|
+
const consoler = require('consoler');
|
|
10
|
+
|
|
11
|
+
module.exports = () => {
|
|
12
|
+
const { webpackConfig, DEV_SERVER_CONFIG } = require('./config/webpack-dev');
|
|
13
|
+
|
|
14
|
+
const app = new express();
|
|
15
|
+
|
|
16
|
+
const compiler = webpack(webpackConfig);
|
|
17
|
+
|
|
18
|
+
// 指定静态文件目录
|
|
19
|
+
app.use(express.static(path.join(__dirname, '../public/dist/')));
|
|
20
|
+
|
|
21
|
+
// 引入 devMiddleware 中间件 监控文件改动
|
|
22
|
+
app.use(
|
|
23
|
+
devMiddleware(compiler, {
|
|
24
|
+
// 落地文件
|
|
25
|
+
writeToDisk: (filePath) => filePath.endsWith('.tpl'),
|
|
26
|
+
// 资源路径
|
|
27
|
+
publicPath: webpackConfig.output.publicPath,
|
|
28
|
+
// headers 配置
|
|
29
|
+
headers: {
|
|
30
|
+
'Access-Control-Allow-Origin': '*',
|
|
31
|
+
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
|
|
32
|
+
'Access-Control-Allow-Headers': 'X-Requested-With, content-type, Authorization',
|
|
33
|
+
},
|
|
34
|
+
stats: {
|
|
35
|
+
colors: true,
|
|
36
|
+
modules: false, // 不显示每个模块的打包信息
|
|
37
|
+
children: false, // 不显示子编译任务的信息
|
|
38
|
+
chunks: false, // 不显示每个代码块的信息
|
|
39
|
+
chunkModules: true, // 显示代码块中模块的信息
|
|
40
|
+
errorDetails: false, // 关闭错误详情
|
|
41
|
+
},
|
|
42
|
+
})
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
// 引入 hotMiddleware 中间件 实现热更新
|
|
46
|
+
app.use(
|
|
47
|
+
hotMiddleware(compiler, {
|
|
48
|
+
path: `/${DEV_SERVER_CONFIG.HMR_PATH}`,
|
|
49
|
+
log: () => {},
|
|
50
|
+
})
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
consoler.info('请等待webpack初次构建完成提示...');
|
|
54
|
+
|
|
55
|
+
// 启动 devServer 服务
|
|
56
|
+
const port = DEV_SERVER_CONFIG.PORT;
|
|
57
|
+
app.listen(port, () => {
|
|
58
|
+
console.log(`app listening on port ${port}`);
|
|
59
|
+
});
|
|
60
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* webpack 启动文件
|
|
3
|
+
* */
|
|
4
|
+
const webpack = require('webpack');
|
|
5
|
+
const webBaseConfig = require('./config/webpack-prod');
|
|
6
|
+
|
|
7
|
+
module.exports = () => {
|
|
8
|
+
console.log('\nwebpack building... \n');
|
|
9
|
+
|
|
10
|
+
webpack(webBaseConfig, (err, stats) => {
|
|
11
|
+
if (err) {
|
|
12
|
+
console.log(err, '---err');
|
|
13
|
+
return;
|
|
14
|
+
// throw err;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
process.stdout.write(
|
|
18
|
+
`${stats.toString({
|
|
19
|
+
colors: true, // 在控制台输出色彩信息
|
|
20
|
+
modules: false, // 不显示每个模块的打包信息
|
|
21
|
+
children: false, // 不显示子编译任务的信息
|
|
22
|
+
chunks: false, // 不显示每个代码块的信息
|
|
23
|
+
chunkModules: true, // 显示代码块中模块的信息
|
|
24
|
+
})}\n`
|
|
25
|
+
);
|
|
26
|
+
});
|
|
27
|
+
};
|
package/babel.config.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
presets: [
|
|
3
|
+
[
|
|
4
|
+
'@babel/preset-env',
|
|
5
|
+
{
|
|
6
|
+
// useBuiltIns: false, 默认值,不对当前的 JS 处理做 polyfill 的填充
|
|
7
|
+
// useBuiltIns: 'usage' 依据用户源代码当中所使用到的新语法进行填充
|
|
8
|
+
// useBuiltIns: 'entry', 依据我们当前筛选出来的浏览器决定填充什么 .browserslistrc 配置进行填充
|
|
9
|
+
useBuiltIns: 'usage',
|
|
10
|
+
corejs: 3, // 因为我们安装的 corejs 的版本是v3 所以需要配置 3
|
|
11
|
+
},
|
|
12
|
+
],
|
|
13
|
+
],
|
|
14
|
+
plugins: ['@babel/plugin-transform-runtime'],
|
|
15
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module.exports = app => {
|
|
2
|
+
return {
|
|
3
|
+
// 判断是否本地环境
|
|
4
|
+
isLocal() {
|
|
5
|
+
return process.env._ENV === 'local';
|
|
6
|
+
},
|
|
7
|
+
// 判断是否测试环境
|
|
8
|
+
isBeta() {
|
|
9
|
+
return process.env._ENV === 'beta';
|
|
10
|
+
},
|
|
11
|
+
// 判断是否生成环境
|
|
12
|
+
isProduction() {
|
|
13
|
+
return process.env._ENV === 'production';
|
|
14
|
+
},
|
|
15
|
+
// 获取当前环境
|
|
16
|
+
get() {
|
|
17
|
+
return process.env._ENV ?? 'local';
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
const Koa = require('koa');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const { sep } = path; // 兼容不同操作系统的斜杆
|
|
4
|
+
|
|
5
|
+
const env = require('./env');
|
|
6
|
+
|
|
7
|
+
// 引入解析器
|
|
8
|
+
const middlewareLoader = require('./loader/middleware');
|
|
9
|
+
const routerSchemaLoader = require('./loader/router-schema');
|
|
10
|
+
const routerLoader = require('./loader/router');
|
|
11
|
+
const controllerLoader = require('./loader/controller');
|
|
12
|
+
const serviceLoader = require('./loader/service');
|
|
13
|
+
const configLoader = require('./loader/config');
|
|
14
|
+
const extendLoader = require('./loader/extend');
|
|
15
|
+
|
|
16
|
+
function start(options = {}) {
|
|
17
|
+
/**
|
|
18
|
+
* 启动项目
|
|
19
|
+
* @param options 项目配置
|
|
20
|
+
* options = {
|
|
21
|
+
* name // 项目名称
|
|
22
|
+
* homePage // 项目首页
|
|
23
|
+
* }
|
|
24
|
+
*/
|
|
25
|
+
// 创建实例
|
|
26
|
+
const app = new Koa();
|
|
27
|
+
// 应用配置
|
|
28
|
+
app.options = options;
|
|
29
|
+
// 基础路径 -> 文件路径/elpis
|
|
30
|
+
app.baseDir = process.cwd();
|
|
31
|
+
// 业务文件路径(sep 是用来兼容不同操作环境中的斜杆) -> 文件路径/elpis/app
|
|
32
|
+
app.businessPath = path.resolve(app.baseDir, `.${sep}app`);
|
|
33
|
+
// 初始化环境配置
|
|
34
|
+
app.env = env();
|
|
35
|
+
|
|
36
|
+
// 加载 middleware
|
|
37
|
+
middlewareLoader(app);
|
|
38
|
+
// 加载 routerSchema
|
|
39
|
+
routerSchemaLoader(app);
|
|
40
|
+
// 加载 controller
|
|
41
|
+
controllerLoader(app);
|
|
42
|
+
// 加载 service
|
|
43
|
+
serviceLoader(app);
|
|
44
|
+
// 加载 config
|
|
45
|
+
configLoader(app);
|
|
46
|
+
// 加载 extend
|
|
47
|
+
extendLoader(app);
|
|
48
|
+
|
|
49
|
+
// 组册elips全局中间件
|
|
50
|
+
try {
|
|
51
|
+
require(path.resolve(__dirname, `..${sep}app${sep}middleware.js`))(app);
|
|
52
|
+
console.log('[start] global elips middleware');
|
|
53
|
+
} catch (e) {
|
|
54
|
+
console.log('[exception] there is no global elips middleware');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// 组册业务全局中间件
|
|
58
|
+
try {
|
|
59
|
+
require(`${app.businessPath}${sep}middleware.js`)(app);
|
|
60
|
+
console.log('[start] global business middleware');
|
|
61
|
+
} catch (e) {
|
|
62
|
+
console.log('[exception] there is no global business middleware');
|
|
63
|
+
}
|
|
64
|
+
// app/middleware.js
|
|
65
|
+
// 注册路由
|
|
66
|
+
routerLoader(app);
|
|
67
|
+
|
|
68
|
+
// 启动服务
|
|
69
|
+
try {
|
|
70
|
+
const port = process.env.PORT || 8080;
|
|
71
|
+
const host = process.env.IP || '0.0.0.0';
|
|
72
|
+
|
|
73
|
+
app.listen(port, host, () => {
|
|
74
|
+
console.log(`server is running port:${port}`);
|
|
75
|
+
});
|
|
76
|
+
} catch (e) {
|
|
77
|
+
console.log(e);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return app;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// 导出实例给外部使用
|
|
84
|
+
module.exports = {
|
|
85
|
+
start,
|
|
86
|
+
};
|