React 簡(jiǎn)易腳手架搭建日志

react-scaffold

搭建日志 - 詳見

寫在前面

開始時(shí)間2018-09-04

本日志僅為FireLeaf-React-Scaffold 2.x搭建過程.

node下載最新版

部分技術(shù)選擇

  • React

  • React-router

  • Redux

  • axios

  • webpack ^4.17.2

UI:

  • antd

  • less

規(guī)范

  • eslint

  • stylelint

init


# 創(chuàng)建項(xiàng)目

mkdir project-name && cd project-name

# init

npm init

創(chuàng)建項(xiàng)目需要文件夾


# build-tools

mkdir build

# products-config

mkdir config

# script

mkdir script

# main-src

mkdir src

# static

mkdir static

webpack

https://www.webpackjs.com/ 4.x


# npm install --save-dev webpack@<version>

npm install --save-dev webpack

npm install --save-dev webpack-cli

# merge

npm install --save-dev webpack-merge

webpack 配置build/

  • webpack.base.config.js: 基礎(chǔ)配置

  • webpack.dev.config.js: dev模式配置

  • webpack.prod.config.js: prod模式配置

Babel

Babel 是一個(gè) JavaScript 編譯器, 進(jìn)行語法轉(zhuǎn)換扩劝,可按需加載插件浩销。

babel 中文

Babel 入門教程

開始


npm i babel-loader@7 babel-core --save-dev

  • babel-loader: 這個(gè)包允許使用babel和webpack來轉(zhuǎn)換JavaScript文件肿男。

  • babel-core: 如果某些代碼需要調(diào)用Babel的API進(jìn)行轉(zhuǎn)碼戏自,就要使用babel-core模塊。


npm install babel-preset-env babel-preset-stage-0 babel-preset-react --save-dev

  • babel-preset-react 用于解析 JSX

  • babel-preset-stage-0 用于解析 ES7 提案

  • babel-preset-env: babel常用的轉(zhuǎn)義器:相當(dāng)于 es2015 ,es2016 ,es2017 及最新版本涮俄。

  • stage-x:

    • Stage 0 - 稻草人: 只是一個(gè)想法夫偶,可能是 babel 插件界睁。

    • Stage 1 - 提案: 初步嘗試。

    • Stage 2 - 初稿: 完成初步規(guī)范兵拢。

    • Stage 3 - 候選: 完成規(guī)范和瀏覽器初步實(shí)現(xiàn)翻斟。

    • Stage 4 - 完成: 將被添加到下一年度發(fā)布。


npm install babel-plugin-transform-runtime --save-dev

  • babel-plugin-transform-runtime: 類babel-polyfill, 按需polyfill

.babelrc 配置


{

  "presets": [

  ["env", {

      "modules": false,

      "targets": {

        "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]

      }

    }],

    "es2015",

    "react",

    "stage-0"

  ],

  "plugins": [

    "transform-runtime"

  ]

}

資源處理

img说铃、fonts访惜、media


npm i url-loader file-loader --save-dev

url-loader

file-loader

編譯css


npm install css-loader style-loader --save-dev

css-loader使你能夠使用類似@import 和 url(...)的方法實(shí)現(xiàn) require()的功能;

style-loader將所有的計(jì)算后的樣式加入頁(yè)面中腻扇; 二者組合在一起使你能夠把樣式表嵌入webpack打包后的JS文件中债热。

使用less

這里使用less, 其他預(yù)編譯樣式配置類似


npm i less less-loader --save-dev

樣式兼容


npm i autoprefixer postcss-loader --save-dev

配置 postcss.config.js


module.exports = {

  plugins: [

    require('autoprefixer')({

      browsers: [

        '>1%',

        'last 4 versions',

        'Firefox ESR',

        'not ie < 9', // React doesn't support IE8 anyway

      ],

      flexbox: 'no-2009',

    })

  ]

};

樣式文件拆分


npm install --save-dev mini-css-extract-plugin

webpack.base.config.js配置


{

  test: /\.css$/,

  exclude: /node_modules/,

  use: [

    MiniCssExtractPlugin.loader,

    'css-loader',

    'postcss-loader'

  ]

},

{

  test: /\.less$/,

  use: [

    MiniCssExtractPlugin.loader,

    'css-loader',

    'postcss-loader',

    'less-loader'

  ]

}

...

plugins: [

  new MiniCssExtractPlugin({

    // Options similar to the same options in webpackOptions.output

    // both options are optional

    filename: "[name].css",

    chunkFilename: "[id].css"

  })

]

webpack-config

webpack-dev

dev模式下webpack配置


npm i --save-dev html-webpack-plugin open-browser-webpack-plugin

webpack-prod

prod模式下webpack配置


npm i --save-dev optimize-css-assets-webpack-plugin

webpack-server

webpack 開發(fā)下的 server配置, 主要有下面兩種方式

webpack-dev-server

https://www.webpackjs.com/guides/development/#%E4%BD%BF%E7%94%A8-webpack-dev-server


npm i --save-dev webpack-dev-server

express + + webpack-dev-middleware

express 服務(wù)(node)+ webpack-dev-middleware + webpack-hot-middleware


npm i --save-dev webpack-dev-middleware webpack-hot-middleware eventsource-polyfill express

# server log

npm i --save-dev rimraf

webpack-build-prod


# 終端 spinner

npm i --save-dev ora rimraf chalk

webpack 其他配置

1、copy靜態(tài)資源 static


npm i --save-dev copy-webpack-plugin

2幼苛、壓縮打包文件


npm i --save-dev zip-webpack-plugin

規(guī)范

代碼窒篱、樣式編碼規(guī)范,代碼簡(jiǎn)潔易讀舶沿,提升項(xiàng)目開發(fā)效率墙杯。:blush:


npm install babel-eslint eslint-plugin-react eslint stylelint stylelint-config-standard --save-dev

vscode + eslint

自動(dòng)檢測(cè)排查,補(bǔ)全修復(fù)


"eslint.autoFixOnSave": true,

    "eslint.validate": [

        // "javascript",

        // "javascriptreact",

        // "html",

        // "vue"

        {

            "language": "javascript",

            "autoFix": true

        },

        {

            "language": "javascriptreact",

            "autoFix": true

        },

        {

            "language": "vue",

            "autoFix": true

        },

        {

            "language": "jsx",

            "autoFix": true

        },

        {

            "language": "html",

            "autoFix": true

        }

    ],

stylelint autofix

樣式自動(dòng)修復(fù)


npm install stylelint-webpack-plugin --save-dev

webpack-config


new StyleLintPlugin({

  // 正則匹配想要lint監(jiān)測(cè)的文件

  files: ['src/**/*.l?(e|c)ss'],

  cache: true,

  fix: true

})

running

package.json 配置 script命令


"scripts": {

  "test": "echo \"Error: no test specified\" && exit 1",

  "lint": "eslint --ext .js src script config test && npm run lint:style",

  "lint:fix": "eslint --fix --ext .js src script config test && npm run lint:style",

  "lint-staged": "lint-staged",

  "lint-staged:js": "eslint --ext .js",

  "lint:style": "stylelint \"src/**/*.less\" --syntax less",

  "start": "node script/server.js", // express server

  "dev": "node script/dev-server.js", // webpack dev  server

  "build": "node script/prod.js" // webpack build prod

}

? 注意 寫進(jìn)package.json中不能帶有注釋

持續(xù)集成服務(wù) Travis CI

綁定 Github 上面的項(xiàng)目括荡,只要有新的代碼高镐,就會(huì)自動(dòng)抓取。然后畸冲,提供一個(gè)運(yùn)行環(huán)境嫉髓,執(zhí)行測(cè)試,完成構(gòu)建邑闲,還能部署到服務(wù)器算行。

React

集成React


npm i --save react react-dom prop-types

react-router

升級(jí) 4.x https://zhuanlan.zhihu.com/p/27433116


npm i --save react-router-dom

# 導(dǎo)入 history

npm i --save history

history跳轉(zhuǎn):

https://github.com/brickspert/blog/issues/3

redux

redux數(shù)據(jù)處理 https://cn.redux.js.org/


npm i --save redux react-redux

react-router-redux

這個(gè)包的正式版4.x不支持react-router v4。你需要用 alpha 版 的react-router-redux苫耸。在package.json 里加入react-router-redux~5.0.0或者用yarn:


yarn add react-router-redux@5.0.0

react應(yīng)用熱更新

https://github.com/gaearon/react-hot-loader/issues/511#issuecomment-288673129


npm i --save-dev react-hot-loader


import React from 'react';

import { render, unmountComponentAtNode } from 'react-dom';

import { Provider } from 'react-redux';

import { AppContainer } from 'react-hot-loader'; 

import thunk from 'redux-thunk';

// 引入路由配置模塊

import RouterList from './router/';

import { createStore, applyMiddleware } from 'redux';

import reducer from './reducer/';

// redux 注入操作

const middleware = [thunk];

const store = createStore(reducer, applyMiddleware(...middleware));

// console.log(store.getState());

const mountNode = document.getElementById('app'); // 設(shè)置要掛在的點(diǎn)

const hotRender = Component => render(

  <AppContainer>

    <Provider store={store}>

      <Component />

    </Provider>

  </AppContainer>

, mountNode);

hotRender(RouterList);

if(process.env.NODE_ENV === 'development') {

  if(module.hot) {

    module.hot.accept('./router/', (err) => {

      if (err) {

        console.log(err);

      }

      const RouterList = require('./router/').default;

      unmountComponentAtNode(mountNode);

      hotRender(RouterList);

    });

  }

}

異步import, code split

異步導(dǎo)入組件纱意,代碼拆分


npm i --save-dev babel-plugin-syntax-dynamic-import

npm i --save react-loadable

配置使用

解決異步loadable引入導(dǎo)致react-hot-loader失效


{

  "presets": [

    "react"

  ],

  "plugins": [

    "syntax-dynamic-import"

  ]

}

import Loadable from 'react-loadable';

import Loading from './Loading';

const LoadableComponent = Loadable({

  loader: () => import('./Dashboard'),

  loading: Loading,

})

export default class LoadableDashboard extends React.Component {

  render() {

    return <LoadableComponent />;

  }

}

Antd

Ant Design 的 React 實(shí)現(xiàn), 螞蟻UI組件庫(kù) ant-design


# install

npm i antd --save

# 按需加載

npm i babel-plugin-import --save-dev

babel-config:


["import", { "libraryName": "antd", "libraryDirectory": "es", "style": true }]

定制主題

config/theme.js:


/**

* antd theme config

*/

const defaultColor = '#4285f4';

module.exports = () => {

  return {

    'primary-color': defaultColor,

    'link-color': defaultColor,

    'border-radius-base': '3px',

    'menu-collapsed-width': '70px',

  };

};

// const fs = require('fs')

// const path = require('path')

// const lessToJs = require('less-vars-to-js')

// module.exports = () => {

//  const themePath = path.join(__dirname, './src/utiles/style/theme.less')

//  return lessToJs(fs.readFileSync(themePath, 'utf8'))

// }

package.json:


"theme": "./config/theme.js",

webpack.base.config.js:


// 獲取theme

const fs = require('fs');

const pkgPath = path.resolve(__dirname, './package.json');

const pkg = fs.existsSync(pkgPath) ? require(pkgPath) : {};

let theme = {};

if (pkg.theme && typeof pkg.theme === 'string') {

  let cfgPath = pkg.theme;

  if (cfgPath.charAt(0) === '.') {

    cfgPath = path.resolve(__dirname, cfgPath);

  }

  const getThemeConfig = require(cfgPath);

  theme = getThemeConfig();

} else if (pkg.theme && typeof pkg.theme === 'object') {

  theme = pkg.theme;

}

...

{

  test: /\.less$/,

  use: [

    MiniCssExtractPlugin.loader,

    'css-loader',

    'postcss-loader',

    {

      loader: 'less-loader',

      options: {

        "sourceMap": true,

        "modules": false,

        "modifyVars": theme,

        'javascriptEnabled': true

      }

    }

  ]

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市鲸阔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌迄委,老刑警劉巖褐筛,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異叙身,居然都是意外死亡渔扎,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門信轿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來晃痴,“玉大人残吩,你說我怎么就攤上這事√群耍” “怎么了泣侮?”我有些...
    開封第一講書人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)紧唱。 經(jīng)常有香客問我活尊,道長(zhǎng),這世上最難降的妖魔是什么漏益? 我笑而不...
    開封第一講書人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任蛹锰,我火速辦了婚禮,結(jié)果婚禮上绰疤,老公的妹妹穿的比我還像新娘铜犬。我一直安慰自己,他們只是感情好轻庆,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開白布癣猾。 她就那樣靜靜地躺著,像睡著了一般榨了。 火紅的嫁衣襯著肌膚如雪煎谍。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評(píng)論 1 285
  • 那天龙屉,我揣著相機(jī)與錄音呐粘,去河邊找鬼。 笑死转捕,一個(gè)胖子當(dāng)著我的面吹牛作岖,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播五芝,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼痘儡,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了枢步?” 一聲冷哼從身側(cè)響起沉删,我...
    開封第一講書人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎醉途,沒想到半個(gè)月后矾瑰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡隘擎,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年殴穴,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡采幌,死狀恐怖劲够,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情休傍,我是刑警寧澤征绎,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站尊残,受9級(jí)特大地震影響炒瘸,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜寝衫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一顷扩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧慰毅,春花似錦隘截、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至着饥,卻和暖如春犀农,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背宰掉。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工呵哨, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人轨奄。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓孟害,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親挪拟。 傳聞我的和親對(duì)象是個(gè)殘疾皇子挨务,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容