em, 要怎么才能不让文章那么枯燥呢?
序言
一篇好的文章, 技术是不是不太必要, 关键是不是要有好的故事呢?
image
故事开始: 从前从前山上有座庙, 庙里有个老和尚, 和一群小和尚. 那天老和尚对小和尚说: 系统大了, 速度慢了, 臃肿了, 是时候优化了. 有个趋势叫 "微前端", 就你了, 搞着去吧.
小和尚:...
小和尚很努力的查找资料, 查看书籍, 准备 demo, 请教大佬. 日子一天天的过去, 眼瞅事情要黄了...
小和尚收拾收拾东西, 赶紧下山...
end
image
故事环境
祖传代码, 一代传一代.
1. 好的, 我们先分析一下当前项目环境吧
- # 进入项目
- cd project/
- # 查看项目下有多少文件
- ls -lR| grep "^-" | wc -l
- => 43305 # 眉头一紧, 事情不对, 这么多文件
- # 删除项目依赖
- rm -rf node_modules
- # 在看一次
- ls -lR| grep "^-" | wc -l
- => 1408 # 眉头又是一紧, 事情没有不对, 就是文件真的多
2. 然后, em, 我们统计一下有多少路由? em, 怎么分析呢?
- const projectRoute = {
- path: "project",
- component: (resolve) => require(["@/vankely/sub-layout.vue"], resolve),
- children: [ {
- path: "shopConditions",
- meta: "/admin/project/shopConditions",
- component: ShopConditionsIndex
- }]
- };
就简单的统计一下'path'出现的次数吧, 虽然不怎么严谨, 但是, 我们不是写技术文章的呀
- grep -rn "path" src/router/ | wc -l
- => 474 # em, 四百多个页面, 教练, 我要去学做菜
3. 我们统计一下编译时间吧
打开命令行, 一顿操作.
yarn dev # 开始编译
=> 项目启动: 2019-06-14 04:14:13
=> ...
=> 期间: 我去上了个厕所
=> 期间: 我去到了杯水
=> 期间: 我发了个呆, 比特币上 100w 美金了
=> ....
=> 项目成功: 2019-06-14 04:18:56
=> 项目耗时: 4 分钟 43 秒
=> Listening at http://0.0.0.0:8080/
em, 就只看我的电脑, 是不是不严谨, 找隔壁的小姐姐问了一下他的启动时间.
p2.jpg
11 分钟, em.
em, 对不起, 公司发的我的笔记本, 再也不嫌弃你性能差了.
后面发现是因为 node 版本太低, 老年车, 拖拉机. 升级到最新的后, 也是 3 分多钟.
em, 垃圾笔记本, 性能真差 (嫌弃的敲了一下笔记本, 结果删了点代码, 隔天真开心).
image
正文
本文不讲那些 webpack 升级, happyPack,DLLPlugin 等等很多技巧.
主要是作用不大, 量变引起质变, 算以上能带来 50% 以上的时间优化, 但是, 文件数量在那, 总和的时间也不会低.
关键原因: 不会.
我们找到根本原因是文件数量太多, 那我们启动的时候给他减肥减肥
1. 找到路由文件, 删, 代码全删了
/src/router/index.JS
只留页面启动必要的页面, 其他的删
- const router = new Router({
- mode: "history",
- routes: [
- {
- path: "/login",
- meta: { permission: "public" },
- component: Login
- },
- {
- path: "/user",
- meta: { permission: "public" },
- component: User
- }
- ]
- });
- export default router;
启动一下: 18 秒.
em, 快是真的快了, 可怎么开发呢?
啥页面都没有.
image
2. 写个脚本动态修改路由文件, 动态添加路由模块
哎呦, 这可真的秀 ~~. ლ(ωლ)
em, 那就建文件专门存放路由模块吧!
然后, 我们就写个脚本专门修改这个文件吧
- src/router/routes-modules.JS
- import routes1 from "./routes1";
- import routes2 from "./routes2";
- import routes3 from "./routes3";
- const syncRoutes = [
- ...routes1,
- ...routes2,
- ...routes3
- ];
- export default syncRoutes;
修改 src/router/index.JS
- import syncRoutes from './routes-modules'
- const router = new Router({
- mode: "history",
- routes: [
- {
- path: "/login",
- meta: { permission: "public" },
- component: Login
- },
- ... syncRoutes
- ]
- });
- export default router;
em, 那我要怎么配置加载什么文件呢?
新增 src/router/router-config.JSON, 为什么用 JSON 呢, 因为开心.(主要是为了方便以后, 方便 es 模块导入和 node 模块导入)
- [
- {
- "name": "模块 1",
- "key": "route1",
- "path": "./route1/index",
- "use": true
- },
- {
- "name": "模块 1",
- "key": "route2",
- "path": "./route2/index",
- "use": false
- },
- {
- "name": "模块 1",
- "key": "route2",
- "path": "./route2/index",
- "use": false
- }
- ]
em, 这个到底是干嘛用的?
经过脚本加工, 然后修改 src/router/routes-modules.JS 文件的内容, 将 "use" 为 true 的输出到文件里面
得到:
- import routes1 from "./routes1";
- const syncRoutes = [
- ...routes1
- ];
- export default syncRoutes;
以上: 就是优化的原理.
3. 脚本实现修改文件
在 webpack 配置文件里, 新增一个脚本文件, 伪代码, 因为细节全上就太多了.
- /build/init-route.JS
- const template = `
- $$$___import___$$$
- const syncRoutes = [
- $$$___routes___$$$
- ];
- export default syncRoutes;
- `;
- const fs = require("fs");
- const path = require("path");
- const isProd = process.env.NODE_ENV === "production";
- // 从项目根目录起
- const resolve = dir => path.join(__dirname, "../..", dir);
- const routesConf = resolve("src/router/router-config.json")
- const routeModules = resolve("src/router/routes-modules.js")
- const initRoute = (modules = []) => {
- let content = template;
- // 文件是否存在, 不存在就生成
- if (fs.existsSync(routeModules)) {
- content=content.replace("$$$___import___$$$", "").replace("$$$___routes___$$$","");
- // 创建文件, 并写入内容
- createFile();
- return;
- }
- const contObj = {
- "$$$___import___$$$": "",
- "$$$___routes___$$$": ""
- }
- routesConf.forEach(r => {
- if (r.use || modules.includes(r.key)) {
- contObj["$$$___import___$$$"] += `\nimport ${rou.key} from "${rou.path}";`;
- contObj["$$$___routes___$$$"] += `\n ...${rou.key},`;
- }
- })
- content=content.replace("$$$___import___$$$", contObj["$$$___import___$$$"])
- .replace("$$$___routes___$$$", contObj["$$$___routes___$$$"]);
- // 将文字内容替换到 src/router/routes-modules.JS
- updateFile(content);
- };
- module.exports = initRoute;
说明:
脚本暴露的方法, 用于传入数组, 然后更新 src/router/routes-modules.JS, 然后 webpack 文件系统, 监听到文件变化自动重启.
4. 脚本怎么用呢? 需要的时候 node build/init-router?
为了更有好的开发, 就想着写个快捷入口, 放页面.
p3.PNG
biubiu,biubiu 生成
组件上的选项来自 "src/router/router-config.json"
当我点击 '生效' 的时候, 将中的 key 传给后端?
em, 没后端!
当我点击生成的时候, 将中的 key 传给谁?
em, 那我当个后端, 牛逼前后端, 全栈 (不接受反驳).
em,webpack 是 express 起的服务.
找到启动 webpack 的 express 文件, 我的叫 devServer.JS.
你的叫什么, 不要问我, 我也不知道.
- /*eslint no-console: 0 */
- const express = require("express");
- const webpack = require("webpack");
- const webpackConfig = require("./webpack.config");
- const bodyParser = require("body-parser");
- const initRoute = require("./sync-router/init-router");
- initRoute([]);
- const App = express();
- App.use(bodyParser.JSON());
- // 添加一个 post 拦截请求 用来监听是否要修改 src/router/routes-modules.JS 文件
- App.post("/__setting", async (req, res) => {
- await initRoute(req.body.routes);
- res.send("hello world"});
- });
- const compiler = webpack(webpackConfig);
- const port = appConfig.devServer.port;
- const devMiddleware = require("webpack-dev-middleware")(compiler,);
- const hotMiddleware = require("webpack-hot-middleware")(compiler);
- App.use(require("connect-history-api-fallback")());
- App.use(devMiddleware);
- App.use(hotMiddleware);
- App.use("/", express.static(utils.resolve("static")));
- App.listen(port, (err) => {
- console.log(`Listening at http://0.0.0.0:${appConfig.devServer.port}/`);
- opn(`http://127.0.0.1:${port}`);
- });
image
5. 最终效果
em, 累死我了.
p4.PNG
上点优化后的启动时间变化:
1.window1o
优化前:
1975557014.jpg
优化后:
335275594.jpg
2.Linux-monjaro
优化前:
优化前
优化后:
优化后
总结
微前端没做成, 倒是达成一项新成就, 逗逼的写了一篇文章.
和尚是没头发的.
em.
来源: http://www.jianshu.com/p/f1ca664cfc29