打包Size减小 80%--App 框架优化

为什么要升级

我们 App 框架是基于vue2+ webpack3 支持国际化的多页面应用,比较通用。文件目录结构大概如下

arduino 复制代码
project/
├── README.md
├── package.json
├── babel.config.js  // Babel配置
├── build/          // webpack配置相关
├── static/          // 静态资源目录
├── src/
│   ├── assets/       // 静态资源文件夹(图片、字体等)
│   ├── components/    // 共享组件
│   ├── pages/         // 多个页面或路由入口
│   │   ├── user/
│   │   │    ├── locales/       // 用户模块相关的国际化语言包
│   │   │    │   ├── en/        // 英语语言包
│   │   │    │   │   └── messages.js
│   │   │    │   ├── zh-CN/     // 简体中文语言包
│   │   │    │   │   └── messages.js
│   │   │    │   └── ...         // 其他语言包
│   │   │    ├── login/
│   │   │    │    ├── index.vue  // 登录页面主组件
│   │   │    │    ├── main.js    // 登录页面入口js
│   │   │    │    └── index.html // (可选)登录页面入口
│   │   │    ├── register/
│   │   │    │    ├── index.vue  // 注册页面主组件
│   │   │    │    ├── main.js    // 注册页面入口js
│   │   │    │    └── index.html // (可选)注册页面入口
│   │   ├── page2/
│   │   └── ...
│   └── utils/              // 工具函数及公用模块
└── .gitignore

框架使用两年后,发现可以从以下方向进一步优化:

  1. 框架不支持新的 ES 语法,比如?.。初步研究方案:需要升级到 babel7,包括它所依赖的 npm 包,那么影响的页面是全量的,全量回归!

  2. 框架构建速度慢。页面数量80个左右,本地服务启动时间约 118 秒,生产构建时间 205 秒。我们另一个项目也是基于此框架,页面数量200个左右,本地服务慢到无法启动。

  3. 页面的公共样式和 js 并没有提取,生产构建包大小 20MB。如果能提取公共文件,比如各页面公用的 vue、vue-i18n 和 lodash 等库可以合并为一个 js 公用。这样构建包会更小,运行时各页面可以共用缓存,同时减少页面首屏渲染时间。

  4. 页面部分静态资源HTTP缓存设置不正确。会导致发版本后文件有更新,用户访问命中到旧的文件。

    1. 有些静态资源比如 style.css,是通引入的,并没有交给 webpack 管理。生产构建后如下
    ini 复制代码
    <link rel="stylesheet" href="style.css">
    1. 静态资源响应头HTTP缓存设置如下,也就是强制缓存2小时。
    ruby 复制代码
    Cache-Control:max-age=7200
  5. 使用webpack-bundle-analyzer分析构建结果:有冗余的js引入。

  6. 使用Chrome lighthouse分析,建议去掉冗余js和css,优化静态资源加载顺序

  7. static目录下的文件是全部复制到构建目录的,包含了大量无用的文件

  8. i18n文件多个页面共用,打包进每个页面,增加了包大小。

i18n文件放在页面级别

pages/user/login和pages/user/register两个页面用i18n文件是这样写的

css 复制代码
module.exports = {
    back: '返回',
    login: {
        title: '登录'
        ...
    },
    register: {
        title: '注册'
        ...
    }
}

这种目录结构的优点:

  1. login和register页面都共用一些国际化Key,比如"back"
  2. 共用的国际化Key,一处修改,全局生效

缺点也很明显

  1. 很难评估某个国际化Key是否是共用的。勉强用了,需要更新的时候,由于难以评估影响范围,只好在页面再声明一份。

    1. 比如back的值需要改为"取消",影响到的页面都要评估下
  2. 构建包包含的国际化文件冗余。比如login页面包括了语言文件中的register对象。

结论:国际化文件放在页面级别

各页面有独立的locales, 调整目录结构如下:

scss 复制代码
src/
2├── pages/
3│   ├── user/
4│   │   ├── login/
5│   │   │    ├── locales/       // 登录页面相关的国际化语言包
6│   │   │    │   ├── en/        // 英语语言包
7│   │   │    │   ├── zh-CN/     // 简体中文语言包
8│   │   │    │   └── ...         // 其他语言包
9│   │   │    ├── index.vue  // 登录页面主组件
10│   │   │    ├── main.js    // 登录页面入口js
11│   │   │    └── (index.html) // (可选)登录页面入口HTML
12│   │   ├── register/
13│   │   │    ├── locales/       // 注册页面相关的国际化语言包
14│   │   │    │   ├── en/        // 英语语言包
15│   │   │    │   ├── zh-CN/     // 简体中文语言包
16│   │   │    │   └── ...         // 其他语言包
17│   │   │    ├── index.vue  // 注册页面主组件
18│   │   │    ├── main.js    // 注册页面入口js
19│   │   │    └── (index.html) // (可选)注册页面入口HTML
20│   └── ...                  // 其他页面或功能模块

login和register有自己独立的locales,优点如下

  1. 修改locales不会影响其他页面

  2. 构建包只包括当前页面下的locales文件

总结

i18n文件放在页面级别,项目构建包大小平均减少30%。

框架升级为Vue-cli

当前框架基于webpack3, 而webpack3 发布于2017年,最新的webpack版本是5。Vue-cli集成了webpack的能力,配置比webpack简单,首先想到的是框架升级为Vue-cli5。

升级步骤

  1. node版本升级16+。因为vue-cli依赖。

  2. 配置文件vue-config.js的主要配置说明:

    1. 页面多入口pages
    2. 提取各页面公共库:vue和vue-i18n为公共js,取名chunk-libs.js
    3. 其他逻辑和原框架webpack配置基本一致。
arduino 复制代码
// 。。。省略处理多页面入口pages

module.exports = defineConfig({
    // ...
    pages, // 多页面入口
    configureWebpack: config => {
        config.resolve = {
            // ...
        };
        config.plugins.push(
            new webpack.DefinePlugin({
            // ...
            })
        );
        if (process.env.NODE_ENV === 'production') {
            config.plugins.push(
                // 复制static目录
                new CopyWebpackPlugin({
                    pattern:[{ from: 'static', to: 'static'}]
                })
            );
            config.plugins.push({
                apply: compiler => {
                    // 构建完成后,处理逻辑
                    compiler.hooks.afterEmit.tap('AfterEmitPlugin', () => {
                        
                    })
                }
            })
        }
    },
    chainWebpack (config) {
        // ... 
        // 提取各页面公共vue和vue-i18n为公共js, 取名为chunk-libs.js
        config.optimization.splitChunks({
            cacheGroups: {
                libs: {
                    name: 'chunk-libs',
                    test: /[\/]node_modules[\/](vue|vue-i18n)/,
                    priority: 10,
                    chunks: 'initial'
                }
            }
        })
    }
})

升级效果

生产构建速度提升约4倍。本地服务启动时间107秒,生产构建时间56秒,包大小17.3MB。

框架升级为Webpack5

为什么要改Vue-cli为webpack5?

  1. 需要修改构建配置提升页面性能,Vue-cli的可定制性不如webpack, 比如: 提取css,压缩css, 去冗余css, 提取公共js等。
  2. Vue-cli相关资料没有webpack丰富
  3. webpack5更流行更通用,易于交流
  4. Vue-cli封装了webpack,webpack更接近原理

升级步骤

  1. 项目结构

    1. 样式文件挪到src/assets/css目录。由页面入口文件main.js引入,这样webpack loader会对样式文件压缩、去冗余处理、提取公共样式文件、生成带hash的文件

    arduino 复制代码
    import '@/assets/css/style.css'
    1. 图片挪到src/assets/images目录。这样webpack会压缩图片,并生成带hash的图片 1```
相关推荐
多多米10051 小时前
初学Vue(2)
前端·javascript·vue.js
看到请催我学习1 小时前
内存缓存和硬盘缓存
开发语言·前端·javascript·vue.js·缓存·ecmascript
golitter.3 小时前
Vue组件库Element-ui
前端·vue.js·ui
道爷我悟了3 小时前
Vue入门-指令学习-v-on
javascript·vue.js·学习
zifer4 小时前
在 Webpack 中使用 TypeScript语言 编写配置文件的完整指南
webpack
.生产的驴4 小时前
Electron Vue框架环境搭建 Vue3环境搭建
java·前端·vue.js·spring boot·后端·electron·ecmascript
老齐谈电商4 小时前
Electron桌面应用打包现有的vue项目
javascript·vue.js·electron
LIURUOYU4213084 小时前
vue.js组建开发
vue.js
九圣残炎5 小时前
【Vue】vue-admin-template项目搭建
前端·vue.js·arcgis
《源码好优多》5 小时前
基于SpringBoot+Vue+Uniapp的植物园管理小程序系统(2024最新,源码+文档+远程部署+讲解视频等)
vue.js·spring boot·uni-app