[译]基于create-react-app打造代码规范化的React项目

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

原文标题: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

翻译:杜梦杰

前言:之前团队内经过讨论和沟通,确定了前端开发规范。规范的执行要由上到下,软硬兼施,除了要求成员们要有自觉性,最好在项目中配置代码规范化/格式化工具。我在配置这些工具时,踩了不少坑,后来有幸看到这篇文章。从头到尾,轻松地将所有工具配置好。本人对于这种规范化的项目比较推崇,拒绝杂乱无章的代码风格,之后的工作中会一直沿用,也推荐大家使用。Keep your code clean!

header.png

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

为了正确的安装这些包,我花了数小时来阅读文档和相关文章,写这篇文章的目的是节省大家的时间。

本指南假定您已经安装了brewnvmyarn。(译者注:原作者使用的是yarn,我在注释中写明了对应的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/",

使用如下命令格式化整个项目:


编辑器中整合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.

检查现有代码

自动修复一些eslint问题:

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中的相关内容
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,
   },
},

修正现有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;

最终成果

最终成果在下面两个Github仓库中:

其他一些有用的包

你可能会用到下面的一些包:

下面列出了create-react-app已使用的包(eject后可以看到)做参考,不要重复安装:

 “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”: “².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”
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,670评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,928评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,926评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,238评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,112评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,138评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,545评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,232评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,496评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,596评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,369评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,226评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,600评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,906评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,185评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,516评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,721评论 2 335

推荐阅读更多精彩内容