<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Vue 2 項目如何快速遷移 Vite 作為開發(fā)工具

          共 11704字,需瀏覽 24分鐘

           ·

          2021-07-10 00:04


          梁曉瑩:  微醫(yī)前端技術(shù)部 一只喜歡讀書??&&游泳????的豬豬女孩~??

          當前版本 [email protected]

          一. 適合什么項目遷移

          1. 使用 vue2 的系統(tǒng)
          2. 內(nèi)部系統(tǒng) - 無需大型流量場景:因為 vite 更迭較快,導(dǎo)致系統(tǒng)需要定期改動基礎(chǔ)功能,造成不穩(wěn)定
          3. 非 ssr 系統(tǒng) - ssr 還有很多問題,暫且等社區(qū)豐富起來
          4. 定期有人維護的系統(tǒng)
          5. 對開發(fā)有痛點而想要改進:比如打包慢,冷啟動慢,HMR 更新慢。。。。
          6. vite 生產(chǎn)環(huán)境用 rollup,但是改造成本大,提效不高,風險大,暫不建議使用。【本人愚見,大佬輕噴】

          二.遷移步驟

          將會以內(nèi)部系統(tǒng)作為案例改造, 開發(fā)用 vite,生產(chǎn)依舊保持 webpack。

          1. 簡單了解 vite 特性。有問題優(yōu)先看vite 官網(wǎng)排查是否有更新或解決方案??!
          2. npm i [email protected] [email protected] [email protected] -D
          3. package.json 添加一個 script -- "vite": "NODE_ENV=development vite"
          4. 關(guān)鍵在于配置 vite.config.js【默認叫做這個文件名,你可配置成其他的。。】
          import { defineConfig } from 'vite';
          import path from 'path';
          import fs from 'fs';

          import { createVuePlugin } from 'vite-plugin-vue2';
          import { injectHtml, minifyHtml } from 'vite-plugin-html';
          import { cjs2esmVitePlugin } from 'cjs2esmodule'
          import dotenv from 'dotenv'
          const config = require('./config')

          try {
            // 根據(jù)環(huán)境變量加載環(huán)境變量文件
            const file = dotenv.parse(fs.readFileSync(`./config/.env.${process.env.NODE_ENV}`), {
              debugtrue
            })
            console.log(file)
            // 根據(jù)獲取的 key 給對應(yīng)的環(huán)境變量賦值
            for (const key in file) {
              process.env[key] = file[key]
            }
          catch (e) {
            console.error(e)
          }
          const API_LOCATION = process.env.API_LOCATION || '/api'

          function resolve(dir{
            return path.join(__dirname, './', dir)
          }
          export default defineConfig({
            root'./'// 項目根目錄(index.html 文件所在的位置)可以是一個絕對路徑,或者一個相對于該配置文件本身的相對路徑。
            publicDir'public'// 作為靜態(tài)資源服務(wù)的文件夾.該值可以是文件系統(tǒng)的絕對路徑,也可以是相對于項目的根目錄的相對路徑。
            base'./'// 公共基礎(chǔ)路徑。改值可以是絕對路徑或空字符串
            mode'development',
            optimizeDeps: { // 要預(yù)構(gòu)建的第三方依賴
              include: []
            },
            resolve: {
              alias: {
                // 'vue': 'vue/dist/vue.esm.js', // 如果是模板解析的 - 使用這個 vue:內(nèi)部為正則表達式  vue 結(jié)尾的
                'vendor': resolve('src/vendor'),
                '@': resolve('src'),
                '~@': resolve('src'),
                '~component': resolve('src/components'),
                '~config': resolve('config'),
              }
            },
            plugins: [
              cjs2esmVitePlugin(), // 將 commonjs 轉(zhuǎn)化為 es module: 有報錯
              createVuePlugin({
                jsxtrue,
                jsxOptions: {
                  injectHfalse,
                },
              }),
              minifyHtml(), // 壓縮 HTML
              injectHtml({ // 入口文件 index.html 的模板注入
                injectData: { // 模板注入的數(shù)據(jù)
                  htmlWebpackPlugin: {
                    options: {
                      isVitetrue,
                      shotcut'/static/img/favicon.png',
                    }
                  },
                  title'HMO 運營后臺',
                },
              }),
            ],
            define: {
              'process.env': process.env
            },
            server: {
              host'liang.myweb.com',
              opentrue// 是否自動打開瀏覽器
              port: process.env.PORT || config.dev.port,
              proxy: {
                [API_LOCATION]: {
                  target'http://127.0.0.1:8001',
                  rewrite(path) => path.replace(API_LOCATION, '')
                }
                
              }
            },
          });

          三.常用問題【踩坑日記??】

          1. vite 目前要求入口文件必須是根目錄下的 index.html,如果之前的 webpack 入口文件同名,需要更改。

          解決方案:vite.config.js:

          import { injectHtml } from 'vite-plugin-html';
          export default defineConfig({
            plugins:[
              injectHtml({ // 入口文件 index.html 的模板注入
                injectData: { // 模板注入的數(shù)據(jù)
                  htmlWebpackPlugin: { // 取和 webpack 插件同名的對象 key,即可
                    options: {
                      isVitetrue,
                      shotcut'/static/img/favicon.png',
                    }
                  },
                  title'HMO 運營后臺'
                },
              })
            ]
          })

          webpack.xxx.js

          new HtmlWebpackPlugin({
            template'index.html',
            injecttrue,
            isVitefalse // 添加標識
          })

          根目錄入口文件 index.html - ejs 模板

                <% if (htmlWebpackPlugin.options.isVite) { %>
                <script type="module" src="/src/main.js"></script>
                <%}%>

          2. 新版本報 xx 錯:可切換舊版本,如 [email protected]

          3.沒有導(dǎo)出命名?

          Uncaught SyntaxError: The requested module '/config/index.js' does not provide an export named 'default'Uncaught SyntaxError: The requested module '/config/index.js' does not provide an export named 'default'

          錯誤原因:瀏覽器僅支持 esm,不支持 cjs vite.config.js

          import { cjs2esmVitePlugin } from 'cjs2esmodule'
          export default defineConfig({
            plugins: [
             cjs2esmVitePlugin(), // 將 commonjs 轉(zhuǎn)化為 es module
            ]
          })

          如果有 require.xx 的按需加載寫法還可以修改成 import 的,案例如下:

          const subjectList = r => require.ensure( [], () => r(require('@/pages/xxx/subject/list.vue')), 'subject' );

          // 改為:Vue 動態(tài)組件 component: ()=>import()

          const subjectList = () => import(/* webpackChunkName: "subject" */ '@/pages/xxx/subject/list.vue')
          const arr = [
            {
              path: '/subject/list',
              name: 'subject/list',
              component: subjectList
              meta: {...}
            }
          ];
          export default arr;

          4. proxy 使用 http-proxy。完整選項詳見 此處.

          案例:

          proxy: {
                '/rest': {
                  target'http://my.web.com/',
                  changeOrigintrue,
                  bypass(req, res, proxyOption) => {
                    console.log(`當前請求代理:${req.url} -> ${proxyOption.target}`);
                  },
                },
              }

          5. ts 文件報錯?

          驗證是否配置了 vite 的 ts 處理

          "compilerOptions": {
            "types": ["vite/client"]
          }

          6. 全局環(huán)境變量報錯?

          // const isProd = ENV === 'production'; // webpack - dev 環(huán)境變量
          // const isProd = import.meta.env.PROD; // vite - dev 環(huán)境變量
          // 可以避開上面????的,采用 NODE_ENV 來區(qū)分:
          const isProd = process.env.NODE_ENV === 'production';

          那么我們啟動的時候:"dev""NODE_ENV=development vite"

          或者可以探索一下社區(qū)的 babel 插件:babel-preset-vite【包含以下兩個功能】babel-plugin-transform-vite-meta-envbabel-plugin-transform-vite-meta-glob

          7. 看一些打印出來的日志&錯誤等?

          cli --debug,或者 vite.config.js 配置打印相關(guān)參數(shù)

          8. 引入文件,比如.vue 的時候,不可以省略擴展名?

          是的!??!不是他們不會做,是他們不想做??,就是這么設(shè)計的,具體請戳這里, 尤大佬推特解釋然后加上 resolve.extensions: ['.vue'] 直接在控制臺報錯:所以沒用。。。

          error: No loader is configured for ".vue"

          害!老老實實加上擴展名!【在線??】 方便的全局加上擴展名方法如下:鏈接

          9. less 文件找不到?

          [vite] Internal server error: '~@/styles/var.less' wasn't found.

          (1)確定已經(jīng)支持 less:npm install -D less(2)別忘了 resolve.alias 也加上一個:'~@': resolve('src')

          10. 如何支持 jsx?

          vite.config.js

          import { createVuePlugin } from 'vite-plugin-vue2';
          createVuePlugin({
            jsxtrue// 配置 jsx
            jsxOptions: {
              injectHfalse,
            },
          })
          Vue.component('my-component',{
           render () {
             return (<div>my template</div>)
            }
          })

          11. 根據(jù)環(huán)境變量配置代理?

          (1)cross-env 來跨平臺設(shè)置環(huán)境變量

          1. 安裝 cross-env

          npm i cross-env -D

          (2)加載環(huán)境變量文件。它能將環(huán)境變量中的變量從 .env 文件加載到 process.env 中

          2. 安裝 dotenv

          npm i dotenv -D

          (3)config/.env.development 配置變量

          NODE_ENV = development
          API_LOCATION = /api
          LOGOUT_PC_LOCATION = http:/
          /user.myweb.com/login
          CRM_ADDRESS = http://crm.myweb.com

          (4)配置 vite.config.ts

          try {
            // 根據(jù)環(huán)境變量加載環(huán)境變量文件
            const file = dotenv.parse(fs.readFileSync(`./config/.env.${process.env.NODE_ENV}`), {
              debugtrue
            })
            console.log(file)
            // 根據(jù)獲取的 key 給對應(yīng)的環(huán)境變量賦值
            for (const key in file) {
              process.env[key] = file[key]
            }
          catch (e) {
            console.error(e)
          }
          const API_LOCATION = process.env.API_LOCATION || '/api'
          ..... 此處省略

          export default defineConfig({
            server: {
              proxy: {
                [API_LOCATION]: {
                  target'http://127.0.0.1:8001',
                  rewrite(path) => path.replace(API_LOCATION, ''// 根據(jù)環(huán)境變量配置代理
                }

              }
            }
          })

          (5)package.json 啟動 script

          "vite""cross-env NODE_ENV=development vite"

          12. 環(huán)境變量報錯?

          原來 webpack 使用的環(huán)境變量 process.env,vite 沒有這個,所以報錯

          Uncaught ReferenceError: process is not defined

          vite 使用的時候import.meta.env, 但是我們老的代碼不想動怎么辦?其實 vite 也還是留了口子給我們定義全局變量[類型不能是 function]

          export default defineConfig({
            // ...
            define: {
              'process.env': {}
            }
          })

          13. anything else?

          ..... bug 無止境,很多都是非通用問題,都是引入 vite 后發(fā)現(xiàn)的系統(tǒng)本身的一些問題,這里就不一一舉例了。后續(xù)會追蹤更多通用問題


          往期推薦

          Vite 太快了,煩死了,是時候該小睡一會了。


          如何實現(xiàn)比 setTimeout 快 80 倍的定時器?


          萬字長文!總結(jié)Vue 性能優(yōu)化方式及原理


          90 行代碼的 webpack,你確定不學(xué)嗎?





          如果你覺得這篇內(nèi)容對你挺有啟發(fā),我想邀請你幫我三個小忙:

          1. 點個「在看」,讓更多的人也能看到這篇內(nèi)容(喜歡不點在看,都是耍流氓 -_-)

          2. 歡迎加我微信「huab119」拉你進技術(shù)群,長期交流學(xué)習(xí)...

            關(guān)注公眾號「前端勸退師」,持續(xù)為你推送精選好文,也可以加我為好友,隨時聊騷。



          點個在看支持我吧,轉(zhuǎn)發(fā)就更好了



          瀏覽 65
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲激情小说区 | 伊人成人在线视频 | 91精品国产一区二区三区四区大 | 国产一级二级 | 无码一区二区麻豆媒体 |