[譯]基于create-react-app打造代碼規(guī)范化的React項(xiàng)目

原文鏈接:https://medium.com/stephenkoo/how-to-set-up-create-react-app-redux-react-router-redux-thunk-prettier-scss-airbnb-eslint-dda0bba5616a

原文標(biāo)題:Set up create-react-app with: Redux, React Router, Redux Thunk, Prettier, SCSS, Airbnb eslint, Standard stylelint, and CSS modules —— A (very) opinionated guide on setting up Create React App

原文作者:Stephen Koo

翻譯:杜夢(mèng)杰

前言:之前團(tuán)隊(duì)內(nèi)經(jīng)過(guò)討論和溝通,確定了前端開發(fā)規(guī)范。規(guī)范的執(zhí)行要由上到下,軟硬兼施,除了要求成員們要有自覺(jué)性,最好在項(xiàng)目中配置代碼規(guī)范化/格式化工具。我在配置這些工具時(shí),踩了不少坑,后來(lái)有幸看到這篇文章。從頭到尾,輕松地將所有工具配置好。本人對(duì)于這種規(guī)范化的項(xiàng)目比較推崇,拒絕雜亂無(wú)章的代碼風(fēng)格,之后的工作中會(huì)一直沿用,也推薦大家使用。Keep your code clean!

header.png

這是一篇在create-react-app中配置流行包的參考指南。

為了正確的安裝這些包,我花了數(shù)小時(shí)來(lái)閱讀文檔和相關(guān)文章,寫這篇文章的目的是節(jié)省大家的時(shí)間。

本指南假定您已經(jīng)安裝了brewnvmyarn。(譯者注:原作者使用的是yarn,我在注釋中寫明了對(duì)應(yīng)的npm命令)

0、安裝Create React App

yarn global add create-react-app
// npm install create-react-app -g
create-react-app your-project-name
cd react-base
git init

1、配置SCSS

yarn add node-sass-chokidar npm-run-all
// npm install node-sass-chokidar npm-run-all --save-dev

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-scripts start",
+    "start": "npm-run-all -p watch-css start-js",
+    "build": "npm run build-css && react-scripts build",
     "test": "react-scripts test --env=jsdom",

src/App.css 重命名為 src/App.scss。

.gitignore中添加:

+# build products
+src/**/*.css

2、配置Prettier

yarn add husky lint-staged prettier
// npm install husky lint-staged prettier --save-dev

新建.prettierrc文件:

{
  'singleQuote': true,
  'trailingComma': 'es5',
}

package.json中添加:

+"lint-staged": {
+  "src/**/*.{js,jsx,json,scss,css}": [
+    "prettier --config .prettierrc --write",
+    "git add"
+  ]
+},
"scripts": {
+    "precommit": "lint-staged",
     "build-css": "node-sass-chokidar --include-path ./src --include-path ./node_modules src/ -o src/",

使用如下命令格式化整個(gè)項(xiàng)目:


編輯器中整合Prettier。(譯者注:非常推薦安裝編輯器插件,1+1>2)

3、配置eslint和eslint-config-airbnb

查看并安裝eslint-config中的所有依賴:

npm info "eslint-config-airbnb@latest" peerDependencies

可以這樣安裝(Linux/OSX用戶):

(
  export PKG=eslint-config-airbnb;
  npm info "$PKG@latest" peerDependencies --json | command sed 's/[\{\},]//g ; s/: /@/g' | xargs yarn add --dev "$PKG@latest"
)

或(Windows用戶):

npm install -g install-peerdeps
install-peerdeps --dev eslint-config-airbnb

新建.eslintrc.js

module.exports = {
  'env': {
    'browser': true,
    'jest': true,
    'es6': true,
    'node': true,
  },
  'extends': [
    'airbnb',
    'prettier',
  ],
  'plugins': [
    'prettier',
  ],
  'rules': {
    'prettier/prettier': ['error', {
      'singleQuote': true,
      'trailingComma': 'es5'
    }],
  },
  'parserOptions': {
    'ecmaFeatures': {
      'jsx': true,
    }
  }
}

src/registerServiceWorker.js文件開頭處添加:

+ /* eslint-disable no-console, no-param-reassign, no-use-before-define */
// In production, we register a service worker to serve assets from local cache.

檢查現(xiàn)有代碼

自動(dòng)修復(fù)一些eslint問(wèn)題:

node_modules/.bin/eslint --ext=js --ext=jsx --fix .

修改src/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';

ReactDOM.render(React.createElement(App), document.getElementById('root'));
registerServiceWorker();

src/App.js 重命名為 src/App.jsx并修改:

import React from 'react';
import logo from './logo.svg';
import './App.css';
const App = () => (
  <div className="App">
    <div className="App-header">
      <img src={logo} className="App-logo" alt="logo" />
      <h2>Welcome to React</h2>
    </div>
    <p className="App-intro">
      To get started, edit <code>src/App.js</code> and save to reload.
    </p>
  </div>
);
export default App;

src/App.test.js 重命名為 src/App.test.jsx并修改:

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
it('renders without crashing', () => {
  const div = document.createElement('div');
  ReactDOM.render(<App />, div);
});

4、配置stylelint和stylelint-config-standard

yarn add stylelint stylelint-config-standard --dev
// npm install stylelint-config-standard --save-dev

新建.stylelintrc

{
  'extends': 'stylelint-config-standard',
}

5、配置eslint和stylelint命令

修改package.json

"lint-staged": {
 + "src/**/*.{js,jsx,json}": [
 +   "eslint --fix",
 +   "prettier --config .prettierrc --write",
 +   "git add"
 + ],
 + "src/**/*.{scss,css}": [
 +   "stylelint --config=.stylelintrc --fix",
 +   "prettier --config .prettierrc --write",
 +   "git add"
 + ]
  },
  "scripts": {
    "precommit": "lint-staged",
    "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-scripts start",
    "start": "npm-run-all -p watch-css start-js",
    "build": "npm run build-css && react-scripts build",
+   "test:lint:js": "eslint --ext=js --ext=jsx .",
+   "test:lint:scss": "stylelint --config=.stylelintrc '**/*.scss'",
+   "test:lint": "run-s test:lint:**",
+   "test:unit": "react-scripts test --env=jsdom",
+   "test": "run-s test:**",
    "eject": "react-scripts eject",
    "eslint-check": "eslint --print-config .eslintrc.js | eslint-config-prettier-check"
  },

6、配置Redux、React Router和Redux Thunk

yarn add redux react-redux react-router-dom react-router-redux@next redux-thunk
// npm install react-redux react-router-dom react-router-redux@next redux-thunk --save

7、配置CSS Modules

  • 警告:本操作需要暴露(eject)create-react-app的配置
  • nulogycss-loader中的相關(guān)內(nèi)容
yarn eject
// npm eject
yarn install
// npm install

修改config/webpack.config.dev.js

{
  loader: require.resolve('css-loader'),
  options: {
    importLoaders: 1,
+   modules: true,
+   localIdentName: "[name]__[local]--[hash:base64:5]"
  },
},

修改config/webpack.config.prod.js

{
  loader: require.resolve('css-loader'),
  options: {
    importLoaders: 1,
+   modules: true,
    minimize: true,
    sourceMap: true,
   },
},

修正現(xiàn)有CSS路徑

刪除css/scss文件類名中的 ‘-’ 。

修改 src/App.jsx

import React from 'react';
import logo from './logo.svg';
import styles from './App.css';
const App = () => (
  <div className={styles.App}>
    <div className={styles.header}>
      <img src={logo} className={styles.logo} alt='logo' />
      <h2>Welcome to React</h2>
    </div>
    <p className={styles.intro}>
      To get started, edit <code>src/App.js</code> and save to reload.
    </p>
  </div>
);
export default App;

最終成果

最終成果在下面兩個(gè)Github倉(cāng)庫(kù)中:

其他一些有用的包

你可能會(huì)用到下面的一些包:

下面列出了create-react-app已使用的包(eject后可以看到)做參考,不要重復(fù)安裝:

 “autoprefixer”: “7.1.2”,
 “babel-core”: “6.25.0”,
 “babel-eslint”: “7.2.3”,
 “babel-jest”: “20.0.3”,
 “babel-loader”: “7.1.1”,
 “babel-preset-react-app”: “^3.0.2”,
 “babel-runtime”: “6.26.0”,
 “case-sensitive-paths-webpack-plugin”: “2.1.1”,
 “chalk”: “1.1.3”,
 “css-loader”: “0.28.4”,
 “dotenv”: “4.0.0”,
 “eslint”: “4.4.1”,
 “eslint-config-react-app”: “2.0.0”,
 “eslint-loader”: “1.9.0”,
 “eslint-plugin-flowtype”: “2.35.0”,
 “eslint-plugin-import”: “2.7.0”,
 “eslint-plugin-jsx-a11y”: “5.1.1”,
 “eslint-plugin-react”: “7.1.0”,
 “extract-text-webpack-plugin”: “3.0.0”,
 “file-loader”: “0.11.2”,
 “fs-extra”: “3.0.1”,
 “html-webpack-plugin”: “2.29.0”,
 “jest”: “20.0.4”,
 “object-assign”: “4.1.1”,
 “postcss-flexbugs-fixes”: “3.2.0”,
 “postcss-loader”: “2.0.6”,
 “promise”: “8.0.1”,
 “react”: “^15.6.1”,
 “react-dev-utils”: “?.0.1”,
 “react-dom”: “^15.6.1”,
 “style-loader”: “0.18.2”,
 “sw-precache-webpack-plugin”: “0.11.4”,
 “url-loader”: “0.5.9”,
 “webpack”: “3.5.1”,
 “webpack-dev-server”: “2.7.1”,
 “webpack-manifest-plugin”: “1.2.1”,
 “whatwg-fetch”: “2.0.3”
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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