目的
為了能夠在工作中更加快速的搭建起開發環境,所以在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-css
和build-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這個檔案,這裡我們用到了shelljs和cross-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相關配置的問題,具體可以看文件