前言
最近需要维护公司的 一个加密的 js 项目。 项目全部由 js 来构建,大概就是由几个 js 文件 最终使用 gulp 将所有的 js 文件成 合并成一个生成环境的 js 文件。 但是由于没有模块化,现在有几个很明显的问题 :
- 方法,变量来路不明。 (开发维护难)
- 污染
window全局。 (容易与客户系统冲突,因为你没法决定客户的开发规范)- 可能存在变量,方法并未使用或者重复,增加了生产环境代码体积
因为, 我们需要在客户的系统的基础之上进行数据的拦截加密, 而客户的系统极其的不稳定。 有新开发的,也有很旧的很老的例如: jsp + 纯静态的 html + css + js 项目。 很容易导致我们 和客户系统进行整合时候 出现很多的线上问题。而我们项目最初是没有进行规范的 模块化 的,这就使得我完完全全要求一行一行的看代码,而且也无法试用编辑器的智能性,帮我找到 这个方法的来自于哪里,需要传入什么,他会返回一个什么结果。这就很让人头疼。下面我总结,记录了一下我的处理流程:
1. 整理项目结构
首先这也是最基础的 ,依据项目所要实现的功能,进行了对应的文件拆分,这就像 一个规范的 Vue , React 项目。比如 下面是一个 vue 项目的大概文件夹关系:
src
|--- assets // 静态资源文件夹
|--- components // 组件文件夹
|--- layout
|---layout.vue
|--- modal
...
|--- pages // 页面文件夹
|--- home
|---index.vue
|--- login
...
|--- utils // 工具类文件夹
|--- api // 接口统一管理文件夹
|--- global.js
|--- login.js
...
|--- main.js
|--- App.vue
|--- router.js
这样子,我们很快就能知道大概的 文件做的事什么事,pages 里面存放的是一个个的页面,他对应的是 router.js 文件当中的路由一一对应。我们就能很快的寻找到对应的文件,来修改对应的代码。
2. 拆分代码
由于混乱在全局,所有很多代码来源不明, 比如,a.js 文件中的一个方法, 他在该文件中并不能找到, 他可能是挂载在 window 全局上被 a 文件所引用着。这样循环嵌套,代码结构很不清晰。 所有 并不能很正确的判断这个方法或者变量有没有被使用,是不是无用代码。
于是,试着倒推一次。从最终的结果出发, 现在这样子认为,我最终打包出来的 js , 如果这里面没有使用到,那么就一定是 无用的代码 ,我们跨越删掉他们。当然, 这样子也只能去掉一部分。 如果有一些代码 他也是无用的,
但是他被引用着,最终也会去到我们 build 出来的包中。这就需要我们进行细看代码逻辑 进行判断是否需要了。
最终我想呈现出来的代码结构大致是这样的 :
// 导入需要的方法
import useHandleRequest from './request/index.js'
improt { enData, deData } from './XXX/XXX.js'
...
// 使用
const handleRequest = useHandleRequest()
handleRequest.onBefore = (req) => {
// 拦截请求加密数据
// 做一些事情
}
handleRequest.onAfter = (req) => {
// 拦截响应解密数据
// 做一些事情
}
首先, 来源清晰了,哪里出现了问题 ,我们可以第一时间找到问题所在。对客户系统进行对应的适配
其次,可能我们需要对新的需求进行叠加,我们就可以很方便的基于原先的代码进行扩展。
这样子, 就把一个 1w,和 5k 行的 js文件拆成了很多单一的 js 文件。每个文件只实现一个功能, 大大提高了代码的可读性。
3. 搭配 webpack
原先的项目代码中,并没有使用任何第三方的 npm 包, 我觉得这是一种损失。 我个人决定,应当进行适量的项目调研, 当有一个能够满足你需求,且在其他方面,例如(项目代码体积)你也可以接受的情况下, 还是应当去使用 npm 上优秀的库的。他们经过了很多攻城狮的努力迭代,可能远比你写的要来的简洁明了。 而且大大降低了你的项目开发周期。
使用 webpack + uglifyjs-webpack-plugin 进行区分环境打包配置 webpack.config.js:
const path = require("path");
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
module.exports = (env, argv) => {
// 基本配置配置
const config = {
entry: "./src/main.js",
output: {
filename: "enc.js",
path: path.resolve(__dirname, "dist"),
},
};
if (argv.mode === "development") {
} else {
// 生产环境 使用uglifyjs 进行代码压缩
config.plugins = [
new UglifyJsPlugin({
uglifyOptions: {
warnings: false,
parse: {},
compress: {
drop_console: true, // 去除console
},
mangle: true, // Note `mangle.properties` is `false` by default.
output: false,
toplevel: false,
nameCache: null,
ie8: true,
keep_fnames: false,
parallel: true,
},
}),
];
}
return config;
};
4. 扩展
在 dev 环境 我们想代码修改就打包新的 js , 不需要我们再去手动去 build 打包文件。
增加 webpack-dev-server , 开启本地服务,运行开发环境。
修改 package.json , 分开两个环境 一个 dev 由 npm run dev 命令运行 ,另一个生产环境, npm run build 运行
"scripts": {
"dev": "webpack-dev-server",
"build": "webpack --mode=production"
},
修改 webpack.config.js : dev 开启本地服务,方便测试代码效果。 build 环境我们只要经过压缩后的 release js 文件即可
const path = require("path");
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
module.exports = (env, argv) => {
// 基本配置配置
let baseConfig = {
mode: "development",
entry: "./src/main.js", //入口文件
};
if (argv.mode === "development") {
// 开发环境
config = {
...baseConfig,
watch: true, // 监听文件变化 自动打包
devServer: {}, // 开启本地服务
};
} else {
// 生产环境
config = {
...baseConfig,
output: {
filename: "enc.js",
path: path.resolve(__dirname, "dist"),
},
plugins: [
new UglifyJsPlugin({
uglifyOptions: {
warnings: false,
parse: {},
compress: {
drop_console: true,
},
mangle: true, // Note `mangle.properties` is `false` by default.
output: {
comments: false,
},
toplevel: false,
nameCache: null,
ie8: true,
keep_fnames: false,
parallel: true,
},
}),
],
};
}
return config;
};
webpack 相关的配置都是阅读文档,以及查阅资料(baidu)。 不对之处请指出。