create-react-app 建立專案有關 less 的若干問題

清秋發表於2018-07-30

在上篇文章使用 Eject 方式在 create-react-app 中使用 Ant Design of React中, 使用 create-react-app 建立了 React 專案,並使用 Eject 方式暴露出了 webpack 的配置,併成功按需引入了 antd。本文主要內容:解決 create-react-app 建立專案後 less 不生效的問題;antd 按需引入 less 原始檔,以及遇到的 bezierEasing.less 檔案報錯問題;antd 本地字型的配置方法;less 使用 css module 的配置。

直接引入less樣式不生效

建立 test.less,並在 App.js 中引入

.test {
  color: red;
}
複製程式碼
// App.js
...
import './test.less'
...
 <div className="test">test</div>
 <Button type="primary">Button</Button>
...
複製程式碼

發現 test 的顏色並沒有生效,因為 create-react-app 沒有內建 less-loader

create-react-app 建立專案有關 less 的若干問題

安裝 lessless-loader ,並修改 webpack 配置

$ cnpm i less less-loader --save-dev
複製程式碼

修改 webpack 配置 修改 webpack.config.dev.jswebpack.config-prod.js 配置檔案, 增加less檔案配置:

// webpack.config.dev.js
...
  {
    test: /\.less$/,
    use: [
      require.resolve('style-loader'),
      {
        loader: require.resolve('css-loader'),
        options: {
          importLoaders: 1,
        },
      },
      {
        loader: require.resolve('less-loader') // compiles Less to CSS
      }
    ],
  },
...
複製程式碼

重啟專案後,less樣式已經生效

create-react-app 建立專案有關 less 的若干問題

antd 的樣式使用 less 原始檔方式引入

babel-plugin-import 中對 style 有這樣對說明:

["import", { "libraryName": "antd" }] : import js modularly

["import", { "libraryName": "antd", "style": true }] : import js and css modularly (LESS/Sass source files)

["import", { "libraryName": "antd", "style": "css" }] : import js and css modularly (css built files)

修改package.json,將style的值改為true

...
  "babel": {
    "presets": [
      "react-app"
     ]
     ],
    "plugins": [
      ["import", { "libraryName": "antd", "libraryDirectory": "es", "style": true }]
    ]
  }
...
複製程式碼

重啟之後,編譯錯誤,提示 bezierEasing.less 檔案的 .bezierEasingMixin() 方法報錯:

create-react-app 建立專案有關 less 的若干問題

按照報錯提供的 issue 地址檢視 : issues/44

原因是因為 less v3 之後廢棄了 Enable Inline JavaScript Option :lesscss.org/usage/#less…

主要有2種解決方式

  • 將 less 版本降到 3.0 以下
  • less loader 增加配置,開啟 JavaScript :
// webpack.config.dev.js
...
  {
-    loader: require.resolve('less-loader') // compiles Less to CSS
+    loader: require.resolve('less-loader'), // compiles Less to CSS
+    options: {
+        javascriptEnabled: true
+    }
    
  }
複製程式碼

重新 npm start,專案可以正常啟動。

antd使用本地字型 iconfont

2018年9月5日更新,9月開學季, ant design 系列迎來了一系列的重大更新。umi 迎來了 2.0 版本, 隨之而來的是 ant design pro 使用 umi 2.0 構建的 2.0 版本。 今天注意到 ant design 的 3.9.0 版本一個重大的更新是對 Icon 進行了重構, 使用 SVG 代替之前的 css font icon。所以如果使用 ant design 3.9.0 以上的版本, 就不會存在離線找不到字型檔案的問題了。如果你使用的 ant design 在 3.9.0 版本以下,可以參考下文離線使用 iconfont 的方式。

Ant Design 預設的 iconfont 檔案託管在 iconfont.cn 並預設使用平臺提供的 alicdn 地址,公網可訪問使用。

由於 alicdn 對部分域名有訪問限制,或者需要內網環境使用,需要將字型下載到本地

最新的 iconfont 檔案可以到 此連結 下載。

create-react-app 建立專案有關 less 的若干問題

下載後將字型檔案放入 public/iconfont/ 路徑下

由於專案使用的是 create-react-app 建立專案,且antd的樣式使用babel-plugin-import按需載入樣式,所以只能採用 定製主題中的 less-loadermodifyVars 配置來覆蓋原來的樣式變數。

具體改動 修改 webpack.config.dev.jswebpack.config-prod.js 配置檔案

// webpack.config.dev.js
...
  {
     loader: require.resolve('less-loader'), // compiles Less to CSS
     options: {
        javascriptEnabled: true,
        modifyVars: {
          "icon-url": "'/public/iconfont/iconfont'"
        }
     }
  }
複製程式碼

重啟專案,成功引入了本地字型

create-react-app 建立專案有關 less 的若干問題

需要注意的是webpack.config-prod.js檔案中的icon-url路徑需要將public替換為生產環境專案檔案路徑,打包之後public中的檔案和資料夾直接複製到bulid路徑下。使用相對路徑會報錯無法編譯,這點不知道有沒有更好的處理方式,希望讀者大神們提供更好的方式。

// webpack.config-prod.js
...
  {
     loader: require.resolve('less-loader'), // compiles Less to CSS
     options: {
        javascriptEnabled: true,
        modifyVars: {
          "icon-url": "'/your-project-name/iconfont/iconfont'"
        }
     }
  }
複製程式碼

css module 形式引入less

增加css-loader的配置

          {
            test: /\.less$/,
            // exclude: [/node_modules/],
            use: [
              require.resolve('style-loader'),
              {
                loader: require.resolve('css-loader'),
                options: {
                   importLoaders: 1,
+                  modules: true
                },
              },
              {
                loader: require.resolve('less-loader'), // compiles Less to CSS
                options: {
                  javascriptEnabled: true,
                  modifyVars: {
                    "icon-url": "'/public/iconfont/iconfont'"
                  }
                }
              }
            ],
          },
複製程式碼

修改App.js,使用css module方式引入

- import './test.less'
+ import styles from './test.less'

    class App extends Component {
      render() {
        return (
          <div className="App">
-           <div className="test">test</div>
+           <div className={styles.test}>test</div>
            <Button type="primary">Button</Button>
          </div>
        );
      }
    }
複製程式碼

重啟專案,css module引入的test樣式生效了,但是antd的按鈕樣式失效了

create-react-app 建立專案有關 less 的若干問題

需要修改 webpack.config.dev.js,只對src中的less檔案開啟css module,這裡寫法有點麻煩,應該有更好的方式。

// webpack.config.dev.js
...
          {
            test: /\.less$/,
            use: [
              require.resolve('style-loader'),
              {
                loader: require.resolve('css-loader'),
                options: {
                  importLoaders: 1
                },
              },
              {
                loader: require.resolve('less-loader'), // compiles Less to CSS
                options: {
                  javascriptEnabled: true,
                  modifyVars: {
                    "icon-url": "'/public/iconfont/iconfont'"
                  }
                }
              }
            ],
          },
          {
            test: /\.less$/,
            include: [/src/],
            use: [
              require.resolve('style-loader'),
              {
                loader: require.resolve('css-loader'),
                options: {
                  importLoaders: 1,
                  modules: true
                },
              }
            ],
          },
...
複製程式碼

2018-08-02更新,評論區有兄弟留言說重新npm install後,css module引入的樣式失效了,今天測試了一下確實有這個問題,試著改了上面的對less檔案處理的loader順序可以解決這個問題,但是原理不是很清楚,還請了解原理的兄弟幫忙指點,多謝

// webpack.config.dev.js
...
          {
            test: /\.less$/,
            include: [/src/],
            use: [
              require.resolve('style-loader'),
              {
                loader: require.resolve('css-loader'),
                options: {
                  importLoaders: 1,
                  modules: true
                },
              }
            ],
          },
          {
            test: /\.less$/,
            use: [
              require.resolve('style-loader'),
              {
                loader: require.resolve('css-loader'),
                options: {
                  importLoaders: 1
                },
              },
              {
                loader: require.resolve('less-loader'), // compiles Less to CSS
                options: {
                  javascriptEnabled: true,
                  modifyVars: {
                    "icon-url": "'/public/iconfont/iconfont'"
                  }
                }
              }
            ],
          },
...
複製程式碼

總結

本文在ejectcreate-react-app的專案基礎上,按需引入了antd,遇到了有關less的若干問題:解決了less檔案不生效的問題,內網環境使用本地iconfont的配置方式,css module的配置方式。本文還有一些配置方式不是最優的方式,希望各位能夠給出更好的方案。

最近在起步 React,準備記錄以下自己的學習和踩坑過程。下一篇文章應該是dva的使用。

參考資料

相關文章