搭建Typescript+React項目模板(2) --- 提升開發(fā)體驗

相關(guān)文章和閱讀順序

搭建Typescript+React項目模板(1) --- 項目初始化
搭建 Typescript+React 項目模板 (2) --- 提升開發(fā)體驗
搭建 Typescript+React 項目模板 (3) --- 整理項目和雜項
搭建 Typescript+React 項目模板 (4) --- 項目打包
搭建 Typescript+React 項目模板 (5) --- 團隊規(guī)范

文章已同步更新到掘金專欄(https://juejin.im/user/5a77c815f265da4e9518bebc/posts)

項目地址

前言

本章主要介紹的是建立在項目初始化的基礎(chǔ)上如何優(yōu)化開發(fā)體驗
內(nèi)容包含如下:

  1. 支持sass
  2. 支持css module
  3. 配置公用的sass屬性
  4. 支持裝飾器
  5. 路徑優(yōu)化
  6. 構(gòu)建緩存
  7. 構(gòu)建加速

支持sass

  • 什么是sass
    sass是一款css預(yù)處理語言,支持變量,嵌套,mixin和導(dǎo)入等功能,可以極大地方便和簡化css寫法。

  • 支持sass
    支持sass首先需要安裝sass-loadernode-sass
    npm install -D node-sass sass-loader
    另外還需要安裝style-loadercss-loader
    npm install -D style-loader css-loader

  • 配置webpack
    在這里有一個點是需要注意的,因為將sass代碼編譯成可用的樣式代碼需要用到三個loader,所以就會產(chǎn)生順序問題,首先sass-loader將sass代碼編譯為css(默認(rèn)使用node-sass),然后css-loader將編譯出來的代碼再次編譯成為符合CommonJS的代碼,最后style-loader將第二步編譯出來的代碼轉(zhuǎn)為js代碼,然后webpack進(jìn)行l(wèi)oader編譯的順序是從下到上的:
    知道上面的順序后我們在webpack中的配置就非常簡單了,直接在module.rules下面加上.scss文件類型的編譯配置即可:

    image.png

  • 查看效果
    這時候我們在src下面新建一個index.scss,然后在index.tsx里面引入這個文件查看效果

    目錄結(jié)構(gòu)

    index.tsx

    index.scss

    效果如圖:
    image.png

支持css module

  • 什么是css module
    css module是針對css類名作用域做出限定的一種規(guī)范,用以解決css類名沖突的問題,此外還能避免一些爬蟲進(jìn)行數(shù)據(jù)爬取(當(dāng)然厲害的爬蟲除外),同等的還有BEM規(guī)范。

  • 安裝對應(yīng)的包
    因為在這里我們用的是TypeScript,所以可以用typings-for-css-modules-loader這個包,這個包也可以替代css-loader的功能,此外這個包還能根據(jù).scss文件里面的類名自動生成對應(yīng)的.d.ts文件:
    npm install -D typings-for-css-modules-loader

  • 配置webpack
    這個配置接非常簡單了,因為要用typings-for-css-modules-loader替代css-loader的功能,所以直接替換即可,將前面sass的配置修改為如下:

    image.png

  • 使用和問題
    這個時候我們將index.tsx文件修改為如下:

    image.png

    修改為這樣既可,但是同時我們也發(fā)現(xiàn)一個問題:
    image.png

    這個問題導(dǎo)致的原因是因為.scss文件中并沒有類似export這樣的關(guān)鍵詞用于導(dǎo)出一個模塊,所以也就導(dǎo)致報錯找不到模塊,這個問題可以通過ts的模塊聲明(declare module)來解決。

  • 解決模塊聲明問題
    這時候我們在根目錄下新建一個typings文件夾,用于存放.scss的模塊聲明,以及后續(xù)需要用到的全局校驗接口,然后新建typed-css-modules.d.ts文件用于存放.scss模塊聲明,目錄結(jié)構(gòu)和聲明內(nèi)容如下:

    image.png

  • 效果
    這個時候回到index.tsx文件中你會發(fā)現(xiàn)錯誤標(biāo)紅消失了,然后我們在index.scss文件中新增如下代碼

    image.png

    保存后你會發(fā)現(xiàn)當(dāng)前目錄下新增了一個index.scss.d.ts文件,打開里面可以發(fā)現(xiàn)是針對每個類名的類型校驗,當(dāng)以后新增類名的時候,typed-css-modules.d.ts都會自動在index.scss.d.ts里面新增對應(yīng)的類型校驗:
    image.png

    這時候回到頁面查看,你會發(fā)現(xiàn)類名變成了一個hash值,這樣可以有效地避免類名全局污染問題:
    image.png

配置公共sass屬性

既然已經(jīng)可以使用sass進(jìn)行更加簡便的css代碼編寫,那么我們也可以將常用的一些樣式代碼和sass變量寫入公共文件中,當(dāng)使用的時候就可以直接引入使用,這可以提高一定的效率節(jié)約時間:

  • 新建公共樣式目錄
    首先在src目錄下新建styles文件夾,然后在styles文件夾下新建var.scss文件用于存放樣式變量。
    之后在var.scss文件里寫入一個顏色變量和一個樣式:

    image.png

  • 查看效果
    然后在index.scss文件里面引入var.scss,接著就可以直接使用里面的變量了:

    image.png

    效果:
    image.png

  • 優(yōu)化
    上面的效果其實已經(jīng)達(dá)成,但還是存在一個不好的問題,就是在引入var.scss的路徑上要根據(jù)每個文件夾的路徑相對來引入非常麻煩,那么我們能否做到只需要@import var.scss就行呢?答案是可以的,我們可以使用一個node-sass的屬性includePaths進(jìn)行路徑優(yōu)化:

    image.png

    image.png

支持裝飾器

  • 前置工作
    在src目錄下新建一個components文件夾,用于存放通用組件,然后在components文件及里面新建一個組件Test,然后在網(wǎng)頁入口引入這個組件,如下圖所示:


    image.png

    image.png
  • 什么是裝飾器,為什么需要裝飾器
    裝飾器本質(zhì)上就是一個函數(shù),這個函數(shù)對類(class)本身進(jìn)行一些處理,也可以將裝飾器的寫法當(dāng)做一種語法糖,如果不用裝飾器的話,可以寫成下圖這樣:


    image.png

    但是如果裝飾器多的話就會變成如下樣子:


    image.png

    這樣會導(dǎo)致代碼非常難以理解,于是裝飾器就登上舞臺了。這在今后使用了mobx(or redux)的時候也是非常有用的。
  • 設(shè)置裝飾器可用
    根據(jù)裝飾器的語法,我們可以將上面的代碼寫成如下:

    image.png

    但是你會發(fā)現(xiàn)這里報了一個錯誤,這是因為裝飾器語法在es6標(biāo)準(zhǔn)中還只是一個提案,并未正式支持,但是在ts中,裝飾器已經(jīng)被正式支持了,不用ts的可以自行安裝babel相關(guān)包進(jìn)行支持。
    image.png

    那么怎么解決這個錯誤呢?我們根據(jù)錯誤提示進(jìn)入到tsconfig文件中,將experimentalDecorators設(shè)置為true即可,然后回到頁面查看log裝飾器已經(jīng)生效了:
    image.png

優(yōu)化路徑

  • 為什么
    在上面的例子中我們新建了components文件夾,然后在入口處引入了其中的Test組件
    image.png

    但是這時候需要考慮到一個問題,如果以后在一個層級比較深的文件中引入這個組件會不會產(chǎn)生如下這種情況呢?
import Test from '../../../../components/Test'

這樣不僅書寫起來麻煩還容易出錯,因此這時候就需要進(jìn)行一些路徑上的優(yōu)化,使得無論在哪個地方引入這些組件都能用同一種寫法,例如:

import Test from '@comonents/Test'
  • 路徑優(yōu)化
    這里針對路徑的優(yōu)化有兩種方案,第一種是直接在webpack.resolve.alias中進(jìn)行路徑配置:
    image.png

    但是在這里我們使用了ts,所以還需要在tsconfig中進(jìn)行配置:
    image.png

    這樣也能用,不過我們還可以用tsconfig-paths-webpack-plugin這個包將tsconfig中對路徑的設(shè)置映射到webpack配置中去,這樣就不需要在webpack中再進(jìn)行一次路徑的配置了,首先安裝:
    npm install -D tsconfig-paths-webpack-plugin
    然后就采用前面tsconfig里面對baseUrlpaths的配置。
    之后進(jìn)入webpack配置中,引入tsconfig-paths-webpack-plugin
    image.png

    接著在webpack.resolve中新增配置項plugins(這里要注意的是新增的不是webpack.plugins,而是webpack.resolve.plugins),配置如下代碼:
    image.png

    接著我們就可以愉快地使用簡化后的路徑了:
    image.png

構(gòu)建緩存

  • 什么是構(gòu)建緩存
    我們一般會使用webpack-dev-server來進(jìn)行項目開發(fā),當(dāng)我們運行webpack-dev-server的時候它會在內(nèi)存中進(jìn)行項目的構(gòu)建,但是當(dāng)使用了babel之類的代碼轉(zhuǎn)換工具后,會對項目構(gòu)建產(chǎn)生較大的性能影響,這是因為每一次的構(gòu)建都會對代碼進(jìn)行重新轉(zhuǎn)換。
    而構(gòu)建緩存就是將構(gòu)建的公用代碼緩存在磁盤上,這樣做的效果就是第一次構(gòu)建的時間花銷會比不用緩存的構(gòu)建大,但是在之后每次構(gòu)建的時間花銷都會大大減少。

  • 對比
    我們拿一個較大的項目來看區(qū)別。
    注: 左邊是沒有設(shè)置構(gòu)建緩存,右邊進(jìn)行了構(gòu)建緩存。
    首先進(jìn)行對比的是第一次構(gòu)建時候的時間花銷:


    image.png

    然后是第二次構(gòu)建的時間花銷:


    image.png

    可以看出在第二次構(gòu)建的時候時間花銷減少了百分之五十以上。
  • 設(shè)置構(gòu)建緩存
    在設(shè)置構(gòu)建緩存之前我們首先要考慮的是那些地方需要進(jìn)行設(shè)置,那么在前面的配置過程中,可以看出花銷較大的地方有對ts(x)的轉(zhuǎn)換并且以后還會添加對應(yīng)的babel進(jìn)去,然后還有針對sass類型的轉(zhuǎn)換,那么我們就先對這兩個地方的轉(zhuǎn)換進(jìn)行配置

  1. 對ts(x)的轉(zhuǎn)換
    這里因為我們使用的是awesome-typescript-loader,這個庫本身自帶了開啟緩存的選項useCache,然后我們需要指定一個保存緩存文件的地方cacheDirectory,所以配置改為如下:
    image.png
  2. sass類型的轉(zhuǎn)換
    這個地方我們需要使用到一個庫cache-loader
    npm install -D cache-loader,
    然后在對.scss文件類型的轉(zhuǎn)換配置中使用它,在這里我們主要是針對轉(zhuǎn)換出來的css進(jìn)行緩存,所以需要寫在typings-for-css-modules-loader配置的前面:
    image.png

    這樣就配置好當(dāng)前的構(gòu)建緩存了,當(dāng)你npm run dev的時候會發(fā)現(xiàn)根目錄下生成了緩存文件.cache-loader。
    image.png

    打開它看會發(fā)現(xiàn)有對應(yīng)的緩存代碼:
    image.png

    不過現(xiàn)在只是根據(jù)目前需要進(jìn)行的緩存配置,當(dāng)后面集成antd等相關(guān)庫的時候因為需要使用到less類型,所以以后還需要根據(jù)需要進(jìn)行添加。

此外,在構(gòu)建這方面的知識在后面的項目打包部分也是非常有用的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容