Vite 打包项目

1,709 阅读2分钟

在浏览器支持 ES 模块之前,开发者没有以模块化的方式开发 JavaScript 的原生机制。这也是 “打包” 这个概念出现的原因:使用工具抓取、处理和链接我们的源码模块到文件中,使其可以运行在浏览器中。

时过境迁,我们见证了许多诸如 webpackRollupParcel 等工具的诞生,这些工具极大地改善了前端开发者的开发体验。

然而,当我们开始构建越来越大型的应用时,需要处理的 JavaScript 代码量也呈指数级增长。大型项目包含数千个模块的情况并不少见。我们开始遇到性能瓶颈 —— 使用 JavaScript 开发的工具通常需要很长时间(甚至是几分钟!)才能启动开发服务器,即使使用 HMR,文件修改后的效果也需要几秒钟才能在浏览器中反映出来。如此循环往复,迟钝的反馈会极大地影响开发者的开发效率和幸福感。

Vite 旨在利用生态系统中的新进展解决上述问题:浏览器开始原生支持 ES 模块,越来越多 JavaScript 工具使用编译型语言编写。

Vite 安装如下

npm init @vitejs/app my-vue-app --template vue

# npm 7+, 需要额外的双横线:
npm init @vitejs/app my-vue-app -- --template vue

# yarn
yarn create @vitejs/app my-vue-app --template vue

npm install

npm run dev

打包 配置如下

//config.js

module.exports = {
  js: {
    hysStatic: "1.6.8",
    vue: "3.0.11",
    vueRouter: "4.0.6",
    weixin: "1.2.0",
    gio: "2.1.35"
  },
  css: {
    hysStatic: "1.5.2"
  }
}
// .env.production

NODE_ENV=production

VITE_APP_ENV=prod
VITE_APP_STATIC_PATH=https://xx.www.org


// vite.config.js
import { defineConfig, loadEnv } from "vite"
import vue from "@vitejs/plugin-vue"
import html from "vite-plugin-html"
import externalGlobals from "rollup-plugin-external-globals"

const path = require("path")
const {
  js: { vue: VueV, vueRouter, weixin, hysStatic: hysStaticJs },
  css: { hysStatic: hysStaticCss }
} = require("./config")

export default ({ mode }) => {
  const { VITE_APP_STATIC_PATH, VITE_APP_IMG_PATH } = loadEnv(
    mode,
    process.cwd()
  )
  console.log(mode, VITE_APP_STATIC_PATH)

  let externalObj = {}
  let injectScript = `<script crossorigin="anonymous" type="text/javascript" src="${VITE_APP_STATIC_PATH}/h5-static/weixin@${weixin}/index.js"></script>`
  if (mode == "develop" || mode == "test" || mode == "release") {
    externalObj = {
      vue: "Vue",
      "vue-router": "VueRouter"
    }
    injectScript = `
    <script crossorigin="anonymous" type="text/javascript" src="${VITE_APP_STATIC_PATH}/h5-static/vue@${VueV}/vue.runtime.prod.js"></script>
    <script crossorigin="anonymous" type="text/javascript" src="${VITE_APP_STATIC_PATH}/h5-static/vue-router@${vueRouter}/vue-router.prod.js"></script>
    <script crossorigin="anonymous" type="text/javascript" src="${VITE_APP_STATIC_PATH}/h5-static/weixin@${weixin}/index.js"></script>
  } else if (mode == "production") {
    externalObj = {
      vue: "Vue",
      "vue-router": "VueRouter",
      "@hysfront/static": "hysStatic"
    }    injectScript = `
     <script crossorigin="anonymous" type="text/javascript" src="${VITE_APP_STATIC_PATH}/h5-static/??vue@${VueV}/vue.runtime.prod.js,vue-router@${vueRouter}/vue-router.prod.js,weixin@${weixin}/index.js"></script>
     `
  }
  const injectGio = `<script crossorigin="anonymous" async defer type="text/javascript" src="${VITE_APP_STATIC_PATH}/h5-static/gio@2.1.35/index.js"></script>`
  return defineConfig({
    plugins: [
      vue(),
      externalGlobals(externalObj),
      html({
        inject: {
          injectData: {
            injectLink: ` 
              <link rel="dns-prefetch" href="${VITE_APP_STATIC_PATH}"/>
              <link rel="dns-prefetch" href="${VITE_APP_IMG_PATH}"/>
              <link href="${VITE_APP_STATIC_PATH}/h5-static/img/favicon.ico" rel="Shortcut Icon" type="image/x-icon" />
            `,
            injectScript,
            injectGio,
            injectCss: `<link rel="stylesheet" type="text/css" href="${VITE_APP_STATIC_PATH}/h5-static/css/hys-static@${hysStaticCss}/index.css"/>`
          }
        },
        minify: true
      })
    ],
    base: mode == "production" ? VITE_APP_STATIC_PATH + "/" : "/",
    resolve: {
      alias: {
        "@": path.resolve(__dirname, "src")
      }
    },
    build: {
      polyfillDynamicImport: true,
      brotliSize: false,
      cssCodeSplit: true,
      assetsDir: "home-static",
      assetsInlineLimit: 10
    },
    server: {
      port: "8080",
      proxy: {
        "^/api": {
          target: "http://api.xxx.com",
          changeOrigin: true
        }
      }
    }
  })
}