React 简易脚手架搭建日志

react-scaffold

搭建日志 - 详见

写在前面

开始时间2018-09-04

本日志仅为FireLeaf-React-Scaffold 2.x搭建过程.

node下载最新版

部分技术选择

  • React

  • React-router

  • Redux

  • axios

  • webpack ^4.17.2

UI:

  • antd

  • less

规范

  • eslint

  • stylelint

init


# 创建项目

mkdir project-name && cd project-name

# init

npm init

创建项目需要文件夹


# 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: 基础配置

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

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

Babel

Babel 是一个 JavaScript 编译器, 进行语法转换,可按需加载插件。

babel 中文

Babel 入门教程

开始


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

  • babel-loader: 这个包允许使用babel和webpack来转换JavaScript文件。

  • babel-core: 如果某些代码需要调用Babel的API进行转码,就要使用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常用的转义器:相当于 es2015 ,es2016 ,es2017 及最新版本。

  • stage-x:

    • Stage 0 - 稻草人: 只是一个想法,可能是 babel 插件。

    • Stage 1 - 提案: 初步尝试。

    • Stage 2 - 初稿: 完成初步规范。

    • Stage 3 - 候选: 完成规范和浏览器初步实现。

    • Stage 4 - 完成: 将被添加到下一年度发布。


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(...)的方法实现 require()的功能;

style-loader将所有的计算后的样式加入页面中; 二者组合在一起使你能够把样式表嵌入webpack打包后的JS文件中。

使用less

这里使用less, 其他预编译样式配置类似


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 开发下的 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 服务(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静态资源 static


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

2、压缩打包文件


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

规范

代码、样式编码规范,代码简洁易读,提升项目开发效率。:blush:


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

vscode + eslint

自动检测排查,补全修复


"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

样式自动修复


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

webpack-config


new StyleLintPlugin({

  // 正则匹配想要lint监测的文件

  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

}

☝ 注意 写进package.json中不能带有注释

持续集成服务 Travis CI

绑定 Github 上面的项目,只要有新的代码,就会自动抓取。然后,提供一个运行环境,执行测试,完成构建,还能部署到服务器。

React

集成React


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

react-router

升级 4.x https://zhuanlan.zhihu.com/p/27433116


npm i --save react-router-dom

# 导入 history

npm i --save history

history跳转:

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

redux

redux数据处理 https://cn.redux.js.org/


npm i --save redux react-redux

react-router-redux

这个包的正式版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应用热更新

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'); // 设置要挂在的点

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

异步导入组件,代码拆分


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

npm i --save react-loadable

配置使用

解决异步loadable引入导致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 实现, 蚂蚁UI组件库 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

      }

    }

  ]

}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 144,100评论 1 305
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 61,765评论 1 257
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 95,393评论 0 213
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 41,312评论 0 183
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 49,108评论 1 260
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 38,923评论 1 178
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 30,527评论 2 274
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,280评论 0 168
  • 想象着我的养父在大火中拼命挣扎,窒息,最后皮肤化为焦炭。我心中就已经是抑制不住地欢快,这就叫做以其人之道,还治其人...
    爱写小说的胖达阅读 29,155评论 6 235
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 32,640评论 0 214
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,391评论 2 216
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 30,744评论 1 231
  • 白月光回国,霸总把我这个替身辞退。还一脸阴沉的警告我。[不要出现在思思面前, 不然我有一百种方法让你生不如死。]我...
    爱写小说的胖达阅读 24,292评论 0 32
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,198评论 2 213
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 31,654评论 3 211
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,655评论 0 9
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,070评论 0 169
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 33,654评论 2 233
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 33,800评论 2 237

推荐阅读更多精彩内容