记一次前端打包优化(二)

1,316 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

采用alias和vite-plugin-cdn-import的方式引入cdn

优化前:

dist/index.html                      0.42 KiB
dist/assets/el-button.8deb3046.css   10.74 KiB / gzip: 1.48 KiB
dist/assets/Home.9c83b2e3.js         0.72 KiB / gzip: 0.47 KiB
dist/assets/index.666ba71a.css       11.27 KiB / gzip: 2.58 KiB
dist/assets/index.4c919ab0.css       87.33 KiB / gzip: 11.70 KiB
dist/assets/index.a15788a8.js        117.97 KiB / gzip: 43.32 KiB
dist/assets/index.10f180e3.js        784.99 KiB / gzip: 251.37 KiB

效果:

dist/index.html                      0.58 KiB
dist/assets/index.666ba71a.css       11.27 KiB / gzip: 2.58 KiB
dist/assets/index.a38a7b90.js        13.94 KiB / gzip: 5.67 KiB
dist/assets/Home.eb394dee.js         1.02 KiB / gzip: 0.58 KiB
dist/assets/el-button.8deb3046.css   10.74 KiB / gzip: 1.48 KiB
dist/assets/index.4c919ab0.css       87.33 KiB / gzip: 11.70 KiB
dist/assets/index.bf92c06d.js        690.48 KiB / gzip: 214.87 KiB

一下子少了一两百K,效果明显,不过还有待继续优化

期间遇到了如下问题:

  1. vite-plugin-cdn-import引入vue之后,打包成功了,但是部署后访问页面时报错了: Uncaught TypeError: Failed to resolve module specifier "vue". Relative references must start with either "/", "./", or "../".
  • Google了好一阵,都没能把这个报错解决,最终只能采用在alias里指定cdn的方式
  1. 采用alias引入vueuse的cdn后,yarn preview时页面是白屏的,查看Console,报错如下: Uncaught SyntaxError: The requested module 'cdn.jsdelivr.net/npm/@vueuse…' does not provide an export named 'useWindowFocus'

把它挪到vite-plugin-cdn-import之后,报了很多类似如下的错误:

TypeError: VueUse.refDebounced is not a function
  • 注:lodash放alias里也会报错,但是它放plugin里就好了
  1. element-plus不管是放在alias还是vite-plugin-cdn-import都能打包成功,但yarn preview会报错 放alias里报:
GET https://cdn.jsdelivr.net/npm/element-plus/+esm/es/components/message/style/css net::ERR_ABORTED 404

放plugin里报:

Uncaught TypeError: Cannot read properties of undefined (reading 'defineComponent')
  • 所以,上面的效果展示的就是没有把vueuse和element-plus加进cdn里的情况

写博客期间,意外的把element-plus的cdn也引入成功了

效果真的是杠杆滴:

% yarn build                                                    22-04-18 - 21:55:47
yarn run v1.22.10
$ vue-tsc --noEmit --skipLibCheck && vite build
vite v2.9.5 building for production...
✓ 1634 modules transformed.
dist/index.html                      0.72 KiB
dist/assets/Home.78f1ca95.js         0.96 KiB / gzip: 0.57 KiB
dist/assets/index.6d9a6aed.js        2.74 KiB / gzip: 1.33 KiB
dist/assets/index.666ba71a.css       11.27 KiB / gzip: 2.58 KiB
dist/assets/el-button.8deb3046.css   10.74 KiB / gzip: 1.48 KiB
dist/assets/el-button.3bcddee7.js    26.17 KiB / gzip: 9.43 KiB
dist/assets/index.4c919ab0.css       87.33 KiB / gzip: 11.70 KiB
dist/assets/index.16b5fd99.js        201.74 KiB / gzip: 67.41 KiB
✨  Done in 27.05s.

完整配置

  1. 需要yarn add --dev vite-plugin-cdn-import
  2. 需要在index.html中引入element-plus的css和引入vue
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="stylesheet" href="//cdn.jsdelivr.net/npm/element-plus@2.1.9/dist/index.css" />
    <script src="//cdn.jsdelivr.net/npm/vue@next"></script>
    <link rel="icon" href="/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>My Chinese Heart</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.ts"></script>
  </body>
</html>
  1. vite中配置plugin和alias
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import importToCDN, { autoComplete } from 'vite-plugin-cdn-import'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    Components({
      resolvers: [ElementPlusResolver()],
    }),
    importToCDN({
      modules: [
        autoComplete('lodash'),
        {
          name: 'element-plus',
          var: 'ElementPlus',
          path: 'https://cdn.jsdelivr.net/npm/element-plus@2.1.9',
        },
      ],
    }),
    AutoImport({
      resolvers: [ElementPlusResolver()],
      imports: [
        'vue',
        'vue-router',
        {
          axios: [
            ['default', 'axios'], // import { default as axios } from 'axios',
          ],
        },
      ],
      eslintrc: {
        enabled: true,
        filepath: './.eslintrc-auto-import.json',
        globalsPropValue: true,
      },
    }),
  ],
  resolve: {
    alias: {
      '@': resolve(__dirname, 'src'),
      vue: 'https://cdn.jsdelivr.net/npm/vue@next/+esm',
      axios: 'https://cdn.jsdelivr.net/npm/axios@next/+esm',
      pinia: 'https://cdn.jsdelivr.net/npm/pinia@next/+esm',
      'vue-router': 'https://cdn.jsdelivr.net/npm/vue-router@next/+esm',
    },
  },
  server: {
    open: true,
    port: 5097,
    cors: true, // 允许跨域
    proxy: {
      '/api': {
        target: 'https://zhongguoren.net',
        changeOrigin: true,
        rewrite: path => path.replace(/^\/api/, ''),
      },
    },
  },
})