<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>

          使用 Webpack5 創(chuàng)建 Vue3 + TS 項目

          共 16688字,需瀏覽 34分鐘

           ·

          2021-06-01 13:27

          點擊上方 前端瓶子君,關(guān)注公眾號

          回復(fù)算法,加入前端編程面試算法每日一題群

          作者:suporka

          https://segmentfault.com/a/1190000039934387

          1. 前言

          筆者兩年前曾寫過一篇文章《Webpack4 搭建 Vue 項目》,后來隨著 webpack5 和 vue3 的面世,一直想升級下我這個 createVue 項目,但是苦于沒有時間(其實是因為懶),一直拖延至今。搗鼓了好幾天,終于搭建好整個項目,因此僅以此文記錄升級搭建的過程。

          PS: 其實也可以用官方腳手架搭建的,為何要自己從頭做起呢?有腳手架我不用,我就折騰。哎,就是玩兒~??

          2. 準備工作

          為何升級?除了折騰外,便是享受新版本帶給我們的新特性體驗。

          Webpack5 的新特性

          • 持久化緩存
          • moduleIds & chunkIds 的優(yōu)化
          • 更智能的 tree shaking
          • Module Federation
          • ...

          Vue3 的新特性

          • 更小
          • 更快
          • 加強 TypeScript 支持
          • 加強 API 設(shè)計一致性
          • 提高自身可維護性
          • 開放更多底層功能

          確定項目技術(shù)棧

          • 編程語言:TypeScript 4.2.4
          • 構(gòu)建工具:[Webpack 5.33.2]()
          • 前端框架:Vue 3.0.11
          • 路由工具:Vue Router 4.0.6
          • 狀態(tài)管理:Vuex 4.0.0
          • CSS 預(yù)編譯:Sass / Less
          • HTTP 工具:Axios
          • Git Hook 工具:Husky + Lint-staged
          • 代碼規(guī)范:EditorConfig + Prettier + ESLint
          • 提交規(guī)范:Commitlint
          • 構(gòu)建部署:Travis

          3. 項目搭建

          此文并不是從零搭建,而是在 [email protected] 的基礎(chǔ)上修改搭建,如若看不懂,可以先看《Webpack4 搭建 Vue 項目》,跟著一步步搭建,后再看此文升級

          創(chuàng)建 createVue 文件夾,進入該文件夾, npm init 初始化項目

          老規(guī)矩,安裝 webpack 四件套npm i webpack webpack-cli webpack-dev-server webpack-merge --save-dev

          當(dāng)前使用版本:
          "webpack""^5.33.2",
          "webpack-bundle-analyzer""^4.4.1",
          "webpack-cli""^4.6.0",
          "webpack-dev-server""^3.11.2",
          "webpack-merge""^5.7.3",

          webpack5 啟動開發(fā)服務(wù)器命令與之前有所變化,從 webpack-dev-server 轉(zhuǎn)變?yōu)?nbsp;webpack serve, 因此 package.json 中 script 的 start 修改為: "start": "webpack serve --progress --hot --inline --config build/webpack.dev.js"

          1. 創(chuàng)建相應(yīng)文件

          與之前沒有太大差異。增加變動的有一下幾點:

          1). 持久化緩存,增加 cache 配置. v5 中緩存默認是 memory,修改設(shè)置"filesystem"寫入硬盤

          // webpack.dev.js
          module.exports = merge(common, {
            cache: {
              type'filesystem',
            }
            //...
          }

          2). 去除插件 clean-webpack-plugin(v5支持),webpack.HashedModuleIdsPlugin(v5更好的 moduleIds & chunkIds),HardSourceWebpackPlugin(v5支持),happypack(v5不兼容)

          安裝 vue 核心解析插件

          解析插件有所不同,從 vue-template-compiler 變成了 @vue/compiler-sfcvue-loader 保持不變。 npm i vue-loader @vue/compiler-sfc --save-dev

          // 當(dāng)前我使用版本
          "vue-loader""^16.2.0",
          "@vue/compiler-sfc""^3.0.11",

          安裝 vue3 及相關(guān)庫,添加 vue 類型文件

          npm i vue@next [email protected] vue-router --save

          src 文件夾下添加 shims-vue.d.ts 文件,解決 vue 類型報錯

          // shims-vue.d.ts
          declare module '*.vue' {
            import type { DefineComponent } from 'vue'
            const component: DefineComponent<{}, {}, any>
            export default component
          }

          安裝 html 模板解析插件

          npm i html-webpack-plugin --save-dev

          安裝 typescript 及解析插件

          npm i typescript ts-loader --save-dev

          配置ts-loader解析:

          // webpack.base.js
          // rules
          {
              test: /\.(t|j)s$/,
              exclude: /node_modules/,
              use: [
                {
                  loader: 'ts-loader',
                  options: {
                    // 指定特定的ts編譯配置,為了區(qū)分腳本的ts配置
                    configFile: path.resolve(__dirname, '../tsconfig.loader.json'),
                    // 對應(yīng)文件添加個.ts或.tsx后綴
                    appendTsSuffixTo: [/\.vue$/],
                  },
                },
              ],
          }

          ts-loader 為單進程執(zhí)行類型檢查和轉(zhuǎn)譯,因此效率有些慢,可以用多進程方案:即關(guān)閉ts-loader的類型檢查,類型檢查由 fork-ts-checker-webpack-plugin 插件執(zhí)行npm i fork-ts-checker-webpack-plugin --save-dev

          // webpack.base.js
          // rules
          {
              test: /\.(t|j)s$/,
              exclude: /node_modules/,
              use: [
                {
                  loader: 'ts-loader',
                  options: {
                    // 指定特定的ts編譯配置,為了區(qū)分腳本的ts配置
                    configFile: path.resolve(__dirname, '../tsconfig.loader.json'),
                    // 對應(yīng)文件添加個.ts或.tsx后綴
                    appendTsSuffixTo: [/\.vue$/],
                    transpileOnly: true, // ? 關(guān)閉類型檢查,即只進行轉(zhuǎn)譯
                  },
                },
              ],
          }
          // plugins push
          new ForkTsCheckerWebpackPlugin()

          至此項目基本可以跑起來了,那么有個問題了:Ts 可以編譯為指定版本的 js,那么還需要 babel 么?

          tsc 的 target 只轉(zhuǎn)譯語法,不集成 polyfill,所以還是得要 babel。

          比如把箭頭函數(shù)轉(zhuǎn)成普通 function、aysnc + await 變成 Promise.then,這是語法轉(zhuǎn)譯;

          但你運行環(huán)境里如果沒有 Promise.prototype.finally,那沒有就還是沒有。

          因此我們項目里還是需要 babel.

          Webpack 轉(zhuǎn)譯 Typescript 現(xiàn)有方案:

          綜合考慮性能和擴展性,目前比較推薦的是 babel+fork-ts-checker-webpack-plugin 方案。

          在 babel7 之前,是需要同時使用 ts-loader 和 babel-loader 的,其編譯過程 TS > TS 編譯器 > JS > Babel > JS 。可見編譯了兩次js,效率有些低下。但是 babel7 出來之后有了解析 typescript 的能力,有了這一層面的支持,我們就可以只使用 babel,而不用再加一輪 ts 的編譯流程了。

          在 babel 7 中,我們使用新的 @babel/preset-typescript 預(yù)設(shè),結(jié)合一些插件便可以解析大部分的 ts 語法。

          那么,Babel 是如何處理 TypeScript 代碼的呢?

          Babel 刪除了所有 TypeScript,將其轉(zhuǎn)換為常規(guī)的 JavaScript,并繼續(xù)以它自己的方式處理。刪除了 typescript 則不需要進行類型檢查,不會有煩人的類型錯誤提醒,因此編譯速度提升,開開心心編程??

          當(dāng)然,類型安全性檢查必不可少,我們可以統(tǒng)一在某個時間集中處理,增加 script:

          "check-types""tsc --watch",

          添加 babel 解析 typescript

          # 安裝以下依賴 --save-dev
          # webpack loader
          babel-loader
          # babel 核心
          @babel/core
          # 智能轉(zhuǎn)換成目標(biāo)運行環(huán)境代碼
          @babel/preset-env
          # 解析 typescript 的 babel 預(yù)設(shè)
          @babel/preset-typescript
          # polyfill 
          @babel/plugin-transform-runtime
          # 支持 ts 類的寫法
          @babel/plugin-proposal-class-properties 
          # 支持三點展開符
          @babel/plugin-proposal-object-rest-spread

          # 安裝以下依賴 --save
          @babel/runtime
          @babel/runtime-corejs3
          "core-js""^3.11.0",

          刪除 ts-loader, 添加 babel-loader

          {
              test: /\.(t|j)s$/,
              exclude: /node_modules/,
              use: [
                {
                  loader: 'babel-loader',
                },
              ],
          }

          項目根目錄添加 babel 配置文件 babel.config.js

          module.exports = {
            presets: [
              [
                '@babel/preset-env',
                {
                  useBuiltIns: 'usage', // 按需引入 polyfill
                  corejs: 3,
                },
              ],
              [
                '@babel/preset-typescript', // 引用Typescript插件
                {
                  allExtensions: true, // 支持所有文件擴展名,否則在vue文件中使用ts會報錯
                },
              ],
            ],
            plugins: [
              [
                '@babel/plugin-transform-runtime',
                {
                  corejs: 3,
                },
              ],
              '@babel/proposal-class-properties',
              '@babel/proposal-object-rest-spread',
            ],
          }

          4. 代碼規(guī)范

          項目中代碼規(guī)范集成了 EditorConfig, Prettier, ESLint, Husky, Lint-staged,以及如何解決 Prettier 和 ESLint 的沖突的問題,具體實現(xiàn)可以參考 《從 0 開始手把手帶你搭建一套規(guī)范的 Vue3.x 項目工程環(huán)境》這篇文章,講的很詳細這里不再贅述。

          5. 提交規(guī)范

          利用 inquirer 選擇配置好的提交類型,以及配合 commitlint 實現(xiàn) commit 檢查

          npm i inquirer shelljs @commitlint/{cli,config-conventional} -D

          添加 package.json 的 script :

          "commitlint""commitlint -e"
          "commit""node commit/git-commit.js"

          創(chuàng)建 commit/git-commit.js 文件

          const shell = require('shelljs')
          const inquirer = require('inquirer')
          const prompsConfig = {
            ciType: [
              {
                type'list',
                name: 'type',
                message: '請選擇本次提交的類型:',
                choices: [
                  {
                    name: '引入新特性',
                    value: 'feat',
                  },
                  {
                    name: '改進代碼的結(jié)構(gòu)格式/樣式',
                    value: 'style',
                  },
                  {
                    name: '修復(fù) bug',
                    value: 'fix',
                  },
                  {
                    name: '提升性能',
                    value: 'perf',
                  },
                  {
                    name: '刪除代碼或文件',
                    value: 'delete',
                  },
                  {
                    name: '其他修改, 比如改變構(gòu)建流程、或者增加依賴庫、工具等',
                    value: 'chore',
                  },
                  {
                    name: '重構(gòu)',
                    value: 'refactor',
                  },
                  {
                    name: '撰寫文檔',
                    value: 'docs',
                  },
                  {
                    name: '增加測試',
                    value: 'test',
                  },
                  {
                    name: '更新打包文件',
                    value: 'build',
                  },
                  {
                    name: '初次提交',
                    value: 'init',
                  },
                  {
                    name: '發(fā)布/版本標(biāo)簽',
                    value: 'release',
                  },
                  {
                    name: '部署功能',
                    value: 'deploy',
                  },
                  {
                    name: '代碼回滾',
                    value: 'revert',
                  },
                  {
                    name: 'CI持續(xù)集成修改',
                    value: 'ci',
                  },
                ],
              },
            ],
            ciMsg: {
              type'input',
              name: 'msg',
              message: '請輸入提交文本:',
              validate: function (value) {
                if (value) {
                  return true
                }
                return '文本必須輸入!'
              },
            },
          }

          async function gitCommit() {
            let { type } = await inquirer.prompt(prompsConfig.ciType)
            let { msg } = await inquirer.prompt(prompsConfig.ciMsg)

            shell.exec(`git commit -m "${type}${msg}"`, function () {
              console.log(`\n提交腳本: git commit -m "${type}${msg}"`)
            })
          }

          gitCommit()

          配置 commitlint 類型,創(chuàng)建 commitlint.config.js 文件:

          module.exports = {
            extends: ['@commitlint/config-conventional'],
            rules: {
              'type-enum': [2, 'always', [
                'build''chore''ci''feat''docs''fix''perf''revert''refactor''style''test''init''build''release''delete'
               ]],
            }
          };

          完成上述操作后,git add 相關(guān)文件,執(zhí)行 npm run commit 即可執(zhí)行 commit 校驗

          6. 構(gòu)建部署 Travis CI

          Travis CI 是一款構(gòu)建和測試的自動化工具,不僅可以提高效率,還能使開發(fā)流程更可靠和專業(yè)化,從而提高軟件的價值。而且,它對于開源項目是免費的,不花一分錢,就能幫你做掉很多事情。詳細介紹可以查看 阮一峰——《持續(xù)集成服務(wù) Travis CI 教程》

          首先,訪問官方網(wǎng)站 travis-ci.org,點擊右上角的個人頭像,使用 Github 賬戶登入 Travis CI。

          找到對應(yīng)的倉庫,打開開關(guān)添加倉庫

          在 github 上 setting/Developer settings/Personal access token 處生成 travis token

          <img src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/69ea45bccd674eaeb7023ea850aa2be1~tplv-k3u1fbpfcp-watermark.image" width="700"/>

          點擊對應(yīng)倉庫的 setting

          設(shè)置環(huán)境變量 GITHUB_TOKEN 為剛才 github 處生成的 token

          <img src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a1594556dfc3449698070dfb99c18f59~tplv-k3u1fbpfcp-watermark.image" width="700"/>

          創(chuàng)建 .travis.yml 配置文件:

          language: node_js
          node_js:
            - 12
          branchs:
            only:
              - master
          cache:
            directories:
              - node_modules
          install:
            - yarn install
          scripts:
            - yarn build
          deploy:
            provider: pages
            local_dir: dist
            skip_cleanup: true
            # 在 GitHub 上生成的令牌,允許 Travis 推送代碼到你的倉庫。
            # 在倉庫對應(yīng)的 Travis 設(shè)置頁面中配置,用于安全控制。
            github_token: $GITHUB_TOKEN
            keep_history: true
            on:
              branch: master

          這樣,當(dāng)你 push 到 master 或者 pr 合并到 master 的時候,就會觸發(fā)部署腳本的執(zhí)行,將生成的 dist 推送至 gh-pages 分支

          <img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/1710d33f1a1c4da18ad28ef2c4805f34~tplv-k3u1fbpfcp-watermark.image" width="700"/>

          7. 存在問題及總結(jié)

          • 構(gòu)建時間比 webpack4 長,可能是由于 ts 的引入,以及 happypack 多進程構(gòu)建的移除造成時間略長
          • dev server 不會自增 port
          • fork-ts-checker-webpack-plugin 無法檢測 vue 中的 ts 類型錯誤

          搗鼓了挺長一段時間,也了解了蠻多工程化的東西,雖然不一定能用于實際項目中,但還是算有所收獲吧!

          最后

          歡迎關(guān)注【前端瓶子君】??ヽ(°▽°)ノ?
          回復(fù)「算法」,加入前端編程源碼算法群,每日一道面試題(工作日),第二天瓶子君都會很認真的解答喲!
          回復(fù)「交流」,吹吹水、聊聊技術(shù)、吐吐槽!
          回復(fù)「閱讀」,每日刷刷高質(zhì)量好文!
          如果這篇文章對你有幫助,在看」是最大的支持
           》》面試官也在看的算法資料《《
          “在看和轉(zhuǎn)發(fā)”就是最大的支持
          瀏覽 80
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

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

          手機掃一掃分享

          分享
          舉報
          <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>
                  免费在线观看黄色视频网站 | 国产精品粉嫩在线播放 | 果冻传媒ⅩXXXXXHD | 成人三级无码 | 无码一级日韩免费 |