itops代码优化之前端代码压缩

系统介绍

基于Python + Django的AD管理系统,系统主要提供以下功能:

  • 丰富的API接口,便于内部系统的集成
  • 在线邮件流查询
  • 常规AD、Exchange操作的WEB化,更友好的交互体验
  • 2FA认证登陆,角色权限分层。增强系统安全性的同时,提升HelpDesk同学解决问题的效率
  • 丰富的报表功能和批量操作功能
  • 详细的日志功能

详细功能可参见基于web的AD、Exchange管理平台

地址:GitHub – openitsystem/itops

代码优化之webpack代码压缩

itops系统源代码大小93 MB,各个目录大小情况如下图

image

frontend目录是itops的前端源文件目录,基于webpack打包的vue.js项目,主要包含源代码+发布文件。

frontend\dist\static\js目录是打包发布后引用js文件的存放目录。可以看下来js目录占到了整个项目的85%,但是源代码最多占用2~3MB的大小,看下来应该是框架的配置问题导致,理论上是有可优化空间的

.map文件剔除

js目录下有很多“.map”文件,vue cli配置文件中可以配置是否开启.map文件的生成,修改 config\index.js 文件内的 productionSourceMap 配置项为false,Vue CLI 官方说明文档

/**
 * Source Maps
 */

productionSourceMap: false,
// https://webpack.js.org/configuration/devtool/#production
devtool: '#source-map',

重新build后项目如下图

image
现在frontend\dist\static\js目录下.map文件没有生成,体积减小超过50%,效果明显,但仍然不理想

开启gzip

目前目录下的文件粗略看下来没有明显不需要的文件生成,但是单js文件体积过大,这时想到的就是gzip。

因为项目是使用uwsgi启动,所以先查一下uwsgi官方文档确定可以支持gzip。

修改 config\index.js 文件内的 productionGzip 配置项为true

// Gzip off by default as many popular static hosts such as
// Surge or Netlify already gzip all static assets for you.
// Before setting to `true`, make sure to:
// npm install --save-dev compression-webpack-plugin
productionGzip: false,
productionGzipExtensions: ['js', 'css'],

根据注释提示我们要安装对应依赖,这里有个版本差异的坑,在我们这个项目中,我使用1.1.12版本来安装

PS > cnpm install --save-dev compression-webpack-plugin@1.1.12
√ Installed 1 packages
√ Linked 6 latest versions
√ Run 0 scripts
√ All packages installed (1 packages installed from npm registry, used 303ms(network 298ms), speed 234.75kB/s, json 7(69.96kB), tarball 0B)

重新build后项目如下图

image

看到目录里有.gz后缀的文件,修改成功,使用uwsgi启动方式需要新增一句命令

static-gzip-dir = /usr/local/its-itops/frontend/

完整配置文件如下

[uwsgi]
http = 0.0.0.0:8080
chdir = /usr/local/its-itops/
plugin = python
wsgi-file = /usr/local/its-itops/itops/wsgi.py
master = 1
processes = 8
threads = 8
uid = 99
gid = 99
static-map = /static=/usr/local/its-itops/static/
static-map = /static=/usr/local/its-itops/frontend/dist/static/
static-map = /static=/usr/python35/lib/python3.5/site-packages/rest_framework/static/
static-gzip-dir = /usr/local/its-itops/frontend/

虽然js文件是经过了压缩,但是整体项目体积反而增大,主要是因为webpack在build的过程中并没有删除原js文件,所以并没有起到缩小体积的作用

根据uwsgi官网针对 static-gzip-dir 功能的描述是,先找对应的js文件,根据js文件名寻找相同名称的.gz文件,那我们把frontend\dist\static\js目录下的js文件全部清空,只保留文件名即可

首先手动删是不现实的

然后好像也没有什么配置可以实现

自己撸一个

webpack针对build提供了插件和钩子,官方文档写的很详细,不过我没看明白,网上找了一篇文章,浅显易懂的介绍了wepack的插件和钩子。点我跳转

主要思路是,写一个自定义插件,在build文件全部生成后,把frontend\dist\static\js目录下的js文件全部清空即可

下面是我写好插件的代码:

let fs = require('fs');
function FileListPlugin(options) {}
FileListPlugin.prototype.apply = function(compiler) {
  compiler.plugin("done", function (stats) {
    var jsfilenamelist = Object.getOwnPropertyNames(stats.compilation.assets)
    for (var i = 0; i < jsfilenamelist.length ; i++) {
      if (jsfilenamelist[i].indexOf('.js.gz') !== -1 && jsfilenamelist[i].indexOf('static/js/') !== -1) {
        fs.writeFileSync('./dist/' + jsfilenamelist[i].replace(/.gz/g,''), ' ')
      }
    }
  });
}
module.exports = FileListPlugin;

在build目录下新建个deloldjs.js文件,把上面代码拷贝到文件里保存

打开编辑 build目录下的webpack.base.conf.js配置文件,添加引用

const FileListPlugin = require('./deloldjs')

module.exports里添加引用插件

module.exports = {
  plugins: [
    new FileListPlugin()
  ],
  ···
  ···
 }

如果没有plugins,则添加整项,如果已经有plugins了,在plugins添加 new FileListPlugin() 即可

这里我踩了一些坑,需要更改build目录下的webpack.prod.conf.js配置文件,为了避免压缩时没能全部压缩带来.gz文件缺失问题,我们修改threshold和minRatio字段如下代码的值,这样可以正确的压缩全部js文件

if (config.build.productionGzip) {
  const CompressionWebpackPlugin = require('compression-webpack-plugin')

  webpackConfig.plugins.push(
    new CompressionWebpackPlugin({
      asset: '[path].gz[query]',
      algorithm: 'gzip',
      test: new RegExp(
        '\\.(' +
        config.build.productionGzipExtensions.join('|') +
        ')$'
      ),
      threshold: 0,
      minRatio: 1,
    })
  )
}

重新build后项目如下图

image

可以看到js目录由最开始的79.8M压缩到现在的7.9M,体积减小超过90%。

效果还是很明显的。

这中间其实还尝试了很多办法,比如路由的懒加载和导入模块的按需引入等,但是效果不是很明显,不过也聊胜于无

发表评论

电子邮件地址不会被公开。 必填项已用*标注