基於React的腳手架搭建

DJL簫氏發表於2018-03-20

目的

為了能夠在工作中更加快速的搭建起開發環境,所以在create-react-app的基礎之上結合自身公司業務和個人習慣,搭建了個更加方便的腳手架。GitHub地址

技術棧

react  // mvm框架
typescipt // 開發語言
sass // 預編譯語言
anti-mobile // UI框架
axios // http請求
react-router-dom // 路由
複製程式碼

目錄結構

core // 存放一些工具程式碼和一些服務
environments  // 存放環境配置檔案
pages // app頁面存放檔案
routing // 路由
components // 公共元件
複製程式碼

搭建過程

1 配置typescript使用環境

首先我打算使用typescript作為開發語言,首先我們是用create-react-app來作為基礎的腳手架工具,按照github上面的操作方法,進行如下操作:

npm install -g create-react-app
create-react-app my-app --scripts-version=react-scripts-ts
cd my-app/
npm start
複製程式碼

這樣當我們就可以通過npm start啟動應用了

配置scss 參考連結

npm install --save node-sass-chokidar

"scripts": {
+  "build-css": "node-sass-chokidar src/ -o src/",
+  "watch-css": "npm run build-css && node-sass-chokidar src/ -o src/--watch --recursive",
   "start": "react-scripts-ts start",
   "build": "react-scripts-ts build",
   "test": "react-scripts-ts test --env=jsdom",
複製程式碼

按照如上操作即可,然後再新增src/**/*.css.gitignore檔案中。接下來我們希望專案能夠監測scss的變化,從而自動去編譯scss檔案,顯然我們要用到watch-cssbuild-css這兩個任務,我們可以使用&&操作符,但是這種跨平臺性並不是很好,所以我們採用npm-run-all這個工具。

npm install --save npm-run-all
複製程式碼

然後進行如下修改

   "scripts": {
     "build-css": "node-sass-chokidar src/ -o src/",
     "watch-css": "npm run build-css && node-sass-chokidar src/ -o src/ --watch --recursive",
-    "start": "react-scripts-ts start",
-    "build": "react-scripts-ts build",
+    "start-js": "react-scripts-ts start",
+    "start": "npm-run-all -p watch-css start-js",
+    "build-js": "react-scripts-ts build",
+    "build": "npm-run-all build-css build-js",
     "test": "react-scripts-ts test --env=jsdom",
     "eject": "react-scripts-ts eject"
   }
複製程式碼

ok,以上我們就搭建好了scss環境

安裝anti-mobile

npm install antd-mobile --save
複製程式碼
npm install react-app-rewired --save-dev
複製程式碼
"scripts": {
	"build-css": "node-sass-chokidar --include-path ./src --include-path ./node_modules src/ -o src/",
	"watch-css": "npm run build-css && node-sass-chokidar --include-path ./src --include-path ./node_modules src/ -o src/ --watch --recursive",
+	"start-js": "react-app-rewired start --scripts-version react-scripts-ts",
    "start": "npm-run-all -p watch-css start-js",
+    "build-js": "react-app-rewired build --scripts-version react-scripts-ts",
    "build": "npm-run-all build-css build-js",
+    "test": "react-app-rewired test --env=jsdom",
    "eject": "react-scripts-ts eject"
  },
複製程式碼

這裡由於我們使用的是typescript,所以"start-js": "react-app-rewired start --scripts-version react-scripts-ts","build-js": "react-app-rewired build --scripts-version react-scripts-ts",後面要加上react-scripts-ts。接下來我們實現按需載入參考連結

安裝npm install babel-plugin-import --save-dev

更改config-overrides.js檔案

/* config-overrides.js */
const tsImportPluginFactory = require('ts-import-plugin')
const { getLoader } = require("react-app-rewired");

module.exports = function override(config, env) {
    const tsLoader = getLoader(
        config.module.rules,
        rule =>
            rule.loader &&
            typeof rule.loader === 'string' &&
            rule.loader.includes('ts-loader')
    );

    tsLoader.options = {
        getCustomTransformers: () => ({
            before: [ tsImportPluginFactory({
                libraryName: 'antd-mobile',
                libraryDirectory: 'es',
                style: 'css',
            }) ]
        })
    };

    return config;
};
複製程式碼

這樣我們就可以直接引入import { Button } from 'antd-mobile';不需要在前面引入import 'antd-mobile/dist/antd-mobile.css';

當我們引入antd-mobile後可能會出現下列錯誤

E:/MyProjects/frame-work-cli/my-app/node_modules/antd-mobile/lib/picker/PropsType.d.ts (7,15): Parameter 'values' implicitly has an 'any' type.

找到node_modules/antd-mobile/lib/picker/PropsType.d.ts把format?: (values) => void;改成 format?: (values: any) => void;即可當然為了直接省事,直接在tsconfig.json設定"noImplicitAny": false

4 開發環境切換配置

現在公司一般都會有開發環境,預釋出環境和正式環境,這些環境所對應的後端地址並不一樣,所以我們要來進行一些配置方便切換。實現的思路就是讀取命令列引數,根據引數把不同環境的配置檔案的內容複製替換掉environment.js這個檔案,這裡我們用到了shelljscross-env(讀取命令列引數)這兩個js庫。 建立cp-environment.js

const shell = require('shelljs');

const env = process.env.NODE_ENV;
const src = `src/environments/environment.${env}.ts`;
const to = `src/environments/environment.ts`;

shell.cp('-R', src, to);
複製程式碼

更改package.json

"scripts": {
    "build-css": "node-sass-chokidar --include-path ./src --include-path ./node_modules src/ -o src/",
    "watch-css": "npm run build-css && node-sass-chokidar --include-path ./src --include-path ./node_modules src/ -o src/ --watch --recursive",
    "start-js": "react-app-rewired start --scripts-version react-scripts-ts",
    "start": "cross-env NODE_ENV=pro npm-run-all cp-environment -p watch-css start-js",
    "startDev": "cross-env NODE_ENV=dev npm-run-all cp-environment -p watch-css start-js",
    "startLocal": "cross-env NODE_ENV=local npm-run-all cp-environment -p watch-css start-js",
    "build-js": "react-app-rewired build --scripts-version react-scripts-ts",
    "build": "cross-env NODE_ENV=pro npm-run-all cp-environment build-css build-js",
    "buildLocal": "cross-env NODE_ENV=Local npm-run-all cp-environment build-css build-js",
    "buildDev": "cross-env NODE_ENV=dev npm-run-all cp-environment build-css build-js",
    "test": "react-app-rewired test --env=jsdom",
    "eject": "react-scripts-ts eject",
    "cp-environment": "node cp-environment.js"
  }
複製程式碼

當然我們開發環境上傳的程式碼應該是buildDev後的程式碼,但是有可能有時進行了誤操作,把build後的程式碼上傳上去,我們還可以寫一個檢測的指令碼。 原理就是讀取當前分支名,根據分知名和當前的環境變數進行對比。

const branchEnvMap = {
  dev: 'dev',
  test: 'test',
  release: 'prod',
};

const shell = require('shelljs');
const branch = shell.exec('git rev-parse --symbolic-full-name --abbrev-ref HEAD', { silent: true }).toString().trim();
const env = process.argv.slice(2).toString().split('=')[1].toString();

if (branchEnvMap[branch] !== env) {
  shell.echo('該分支對應的編譯任務不是這個,請檢查執行的命令!', branch, env);
  shell.exit(1);
}
複製程式碼

Http

用到就是axios,至於怎麼用直接看我的GitHub地址就行,這裡進行了一層封裝,主要是對返回的結果進行統一的處理。

路由

我用到的是react-router-dom,至於用法還是推薦看github,

1 E:/MyProjects/frame-work-cli/my-app/node_modules/@types/react-dom/node_modules/@types/react/index.d.ts (3631,13): Subsequent property declarations must have the same type.
Property 'a' must be of type 'DetailedHTMLProps<AnchorHTMLAttributes, HTMLAnchorElement>', but here has type 'DetailedHTMLProps<AnchorHTMLAttributes, HTMLAnchorElement>'.

當我們啟動應用的時候可能會出現如上錯誤,這是由於我們安裝的@types/react@types/react-dom版本並不怎麼一致,參考連結, 例如下面的版本

 "@types/react": "^15.6.7",
 "@types/react-dom": "^16.0.3",
複製程式碼

所以我們可以換成

"@types/react": "^16.0.36", 
"@types/react-dom: "^16.0.3"
複製程式碼

2 E:/MyProjects/frame-work-cli/my-app/node_modules/antd-mobile/lib/picker/PropsType.d.ts(7,15): Parameter 'values' implicitly has an 'any' type.

在tsconfig.json設定"noImplicitAny": false

3 error TS1192: Module '"react"' has no default export.

設定 tsconfig.json "allowSyntheticDefaultImports": true,

4 expected parameter: 'props' to have a typedef

在tslint.json設定typedef: false,這個屬於tslint相關配置的問題,具體可以看文件

最後(歡迎大家關注我)

DJL簫氏個人部落格

部落格GitHub地址

簡書

掘金

相關文章