從0到1快速構建基於create-react-app的腳手架

create-react-app 是業界最優秀的 React 應用開發工具之一,本文會帶你從0到1建立基於create-react-app的工程。javascript

快速構建一個React App

npx create-react-app my-app     
cd my-app
npm start
複製代碼

注意使用npx要你的npm要在 5.2.0以上,npx會幫你執行依賴包裏的二進制文件,這裏很少作敘述; 構建完成後css

  • 進入目錄
  • 命令行輸入npm start啓動應用
  • npm run build打包應用

npm start

進入你的項目後你會看到以下的文件目錄html

my-app
├── README.md
├── node_modules
├── package.json
├── .gitignore
├── public
│   └── favicon.ico
│   └── index.html
│   └── manifest.json
└── src
    └── App.css
    └── App.js
    └── App.test.js
    └── index.css
    └── index.js
    └── logo.svg
    └── registerServiceWorker.js
複製代碼

移動配置項

有意思的事情來了,你並無看到關於webpack的配置, 因而去package.json裏查看一下script,以下:java

"scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  }
複製代碼

命令都是經過react-scripts發起的,猜想是 react-scripts 是一個包,去node_modules裏找一下,果真如此;node

react-scripts 是一個生成的項目所須要的開發依賴,目錄以下:react

react-scripts
├── README.md
├── node_modules
├── package.json
├── bin
│   └──react-scripts.js
├── config
│   └── jest
│   └── env.js
│   └── paths.js
│   └──polyfills.js
│   └──webpack.config.dev.js
│   └──webpack.config.prod.js
│   └──webpackDevServer.config.js
└── scripts
    └── utils
       └──createJestConfig.js
    └── build.js
    └── eject.js
    └── init.js
    └── start.js
    └── test.js
    └── template
複製代碼

執行webpack

npm run eject
複製代碼

你會看到 react-scripts 的配置放到了你的項目的根目錄下,同時查看package.json也有相應的變化,這裏create-react-app已經幫你把須要的安裝依賴添加的node_modules裏;git

既然要實現可高度自定義配置,就把babel編譯所須要的插件也都單獨放到咱們本身的項目裏吧; 根目錄下新建presets.js ,查看babel-preset-react-app包下的文件,把index文件內容放入presets.js,並把babel-preset-react-app包下的項目依賴放入本身的項目下 修改config/jest/babelTransform.jsgithub

module.exports = babelJest.createTransformer({
  presets: [require.resolve('../presets.js')],
  babelrc: false,
});
複製代碼

至此,若是你須要再添加什麼插件就能夠在presets.js裏自行引入了,例如我但願在項目裏可使用es7的裝飾器,就引入了 babel-plugin-transform-decorators-legacyweb

require.resolve('babel-plugin-transform-decorators-legacy')
複製代碼

並在.babelrc裏配置

{
    "presets": [
      "es2015",
      "react",
      "stage-0",
      "react-native-stage-0/decorator-support"
    ],
    "plugins": [
      "transform-decorators-legacy",
      "transform-runtime", ["import",{"libraryName":"antd","style":true}]
    ]
  }
複製代碼

一樣的,若是你須要引入某個polyfills,在config/polyfills.js裏添加就ok; 好比我添加了

require("babel-polyfill");
require("babel-register");
複製代碼

執行 npm start 試一下 以上咱們就完成了把配置文件從react-scripts移到咱們本身的項目裏,彆着急,這只是第一步;

下面咱們開始咱們的自定義配置

添加CSS預處理器(Sass, Less 等)

根據須要配置,這裏我添加了Sass; 首先,咱們須要先安裝Sass

npm install --save node-sass-chokidar
複製代碼

修改package.json 文件

"scripts": {
+    "build-css": "node-sass-chokidar src/ -o src/",
+    "watch-css": "npm run build-css && node-sass-chokidar src/ -o src/ --watch --recursive",
     "start": "node scripts/start.js",
     "build": "node scripts/build.js",
     "test": "node scripts/test.js --env=jsdom",
     "eject": "node scripts/eject.js"
}
複製代碼

咱們須要在啓動的時候同時執行watch-css和start.js,因此須要安裝一個包npm-run-all

npm install --save npm-run-all
複製代碼

修改package.json文件

"build-css": "node-sass-chokidar src/ -o src/",
     "watch-css": "npm run build-css && node-sass-chokidar src/ -o src/ --watch --recursive",
-    "start": "node scripts/start.js",
-    "build": "node scripts/build.js",
+    "start-js": "node scripts/start.js",
+    "start": "npm-run-all -p watch-css start-js",
+    "build-js": "node scripts/build.js",
+    "build": "npm-run-all build-css build-js",
複製代碼

這個時候你能夠在項目裏使用scss文件寫樣式,例如咱們把App.css 更名爲App.scss,並使用scss語法編寫樣式,執行命令

npm start
複製代碼

你會看到會自動再生成一個編譯好的和scss文件同名的css文件;

Post-Processing CSS

你沒必要作任何設置,create-react-app的原有的配置已經幫你作了; 這個設置會壓縮你的CSS,並經過Autoprefixer自動將供應商前綴添加到它中,你沒必要擔憂了各個瀏覽器的兼容問題了。

添加 Router

首先安裝 react-router-dom

npm install --save react-router-dom
複製代碼

這裏給出一個簡單的react-router-dom例子

import React from "react";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";

const BasicExample = () => (
  <Router>
    <div>
      <ul>
        <li>
          <Link to="/">Home</Link>
        </li>
        <li>
          <Link to="/about">About</Link>
        </li>
        <li>
          <Link to="/topics">Topics</Link>
        </li>
      </ul>

      <hr />

      <Route exact path="/" component={Home} />
      <Route path="/about" component={About} />
      <Route path="/topics" component={Topics} />
    </div>
  </Router>
);

const Home = () => (
  <div>
    <h2>Home</h2>
  </div>
);

const About = () => (
  <div>
    <h2>About</h2>
  </div>
);

const Topics = ({ match }) => (
  <div>
    <h2>Topics</h2>
    <ul>
      <li>
        <Link to={`${match.url}/rendering`}>Rendering with React</Link>
      </li>
      <li>
        <Link to={`${match.url}/components`}>Components</Link>
      </li>
      <li>
        <Link to={`${match.url}/props-v-state`}>Props v. State</Link>
      </li>
    </ul>

    <Route path={`${match.url}/:topicId`} component={Topic} />
    <Route
      exact
      path={match.url}
      render={() => <h3>Please select a topic.</h3>}
    />
  </div>
);

const Topic = ({ match }) => (
  <div>
    <h3>{match.params.topicId}</h3>
  </div>
);

export default BasicExample;
複製代碼

具體關於react-router-dom的用法請參考官網

vw方案在create-react-app實施

webpack配置變更:

// 修改webpack配置
{
  loader: require.resolve('postcss-loader'),
  options: {
    config: {
      path: 'postcss.config.js'  // 這個得在項目根目錄建立此文件
    },
    // Necessary for external CSS imports to work
    // https://github.com/facebookincubator/create-react-app/issues/2677
    ident: 'postcss'
    // plugins: () => [
    //   require('postcss-flexbugs-fixes'),
    //   autoprefixer({
    //     browsers: [
    //       '>1%',
    //       'last 4 versions',
    //       'Firefox ESR',
    //       'not ie < 9', // React doesn't support IE8 anyway // ], // flexbox: 'no-2009', // }), // ], }, }, 複製代碼

根目錄新建 postcss.config.js

module.exports = {
    "plugins": [
        require('postcss-flexbugs-fixes'),
        require("autoprefixer")({
            browsers: [
                '>1%',
                'last 4 versions',
                'Firefox ESR',
                'not ie < 9', // React doesn't support IE8 anyway ], flexbox: 'no-2009', }), require("postcss-aspect-ratio-mini"), require("postcss-write-svg")({ utf8: false }), require("postcss-cssnext")({ features: { autoprefixer: false, } }), require("postcss-px-to-viewport")({ viewportWidth: 750, viewportHeight: 1334, unitPrecision: 3, viewportUnit: 'vw', selectorBlackList: ['.ignore', '.hairlines'], minPixelValue: 1, mediaQuery: false }), require("postcss-viewport-units"), require("cssnano")({ preset: "advanced", autoprefixer: false, "postcss-zindex": false }) ] } 複製代碼

上面的配置中,postcss-px-to-viewport能夠然咱們像原來同樣去寫px

viewportWidth和viewportHeight的配置根據大家家ui給出的設計稿來定就行了。

postcss-write-svg插件主要經過使用border-image和background來作1px的相關處理。好比 咱們先寫一個1像素邊框

@svg 1px-border {
  height: 2px; 
  @rect { 
    fill: var(--color, black); 
    width: 100%; 
    height: 50%; 
    } 
  } 
複製代碼

在須要的時候就能夠這樣使用

.example { 
  border: 1px solid transparent; 
  border-image: svg(1px-border param(--color #00b1ff)) 2 2 stretch; 
  }
複製代碼

固然還有background-image的實現方式,具體參考postcss-write-svg

安裝插件

npm i postcss-aspect-ratio-mini postcss-px-to-viewport postcss-write-svg postcss-cssnext postcss-viewport-units cssnano cssnano-preset-advanced --D
複製代碼

package.json文件中:

"dependencies": {
   "cssnano": "^3.10.0", 
   "postcss-aspect-ratio-mini": "0.0.2", 
   "postcss-cssnext": "^3.1.0", 
   "postcss-px-to-viewport": "0.0.3", 
   "postcss-viewport-units": "^0.1.3", 
   "postcss-write-svg": "^3.0.1", 
   },

複製代碼

注意:autoprefixery一次就夠了 在cssnano和postcss-cssnext把默認配置改成false,不然會影響性能

接下來,修改 public/index.html 主要有三個地方

  1. 修改 meta viewport爲了適配iponeX 添加viewport-fit=cover
<meta name=viewport content="width=device-width,initial-scale=1,user-scalable=no,viewport-fit=cover">
複製代碼
  1. 引入 viewport-units-buggyfill.hacks的ali cdn
<script src="//g.alicdn.com/fdilab/lib3rd/viewport-units-buggyfill/0.6.2/??viewport-units-buggyfill.hacks.min.js,viewport-units-buggyfill.min.js"></script>
複製代碼
  1. 初始化執行ali cdn的init方法
<script>
      window.onload = function () {
        window.viewportUnitsBuggyfill.init({
          hacks: window.viewportUnitsBuggyfillHacks
        });

        var winDPI = window.devicePixelRatio;
            var uAgent = window.navigator.userAgent;
            var screenHeight = window.screen.height;
            var screenWidth = window.screen.width;
            var winWidth = window.innerWidth;
            var winHeight = window.innerHeight;
            console.log(
                "Windows DPI:" + winDPI +
                ";\ruAgent:" + uAgent +
                ";\rScreen Width:" + screenWidth +
                ";\rScreen Height:" + screenHeight +
                ";\rWindow Width:" + winWidth +
                ";\rWindow Height:" + winHeight
            )
      }
</script>
複製代碼

另外,還能夠經過媒體查詢對iphoneX可能出現的兼容問題進行hack, 代碼以下:

@media only screen and (device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) {
   /* iPhone X 獨有樣式寫在這裏*/ 
   
}
複製代碼

引入可高度自定義配置主題的 antd

若是你的項目須要引入antd請參考這裏

安裝react-app-rewired用來重寫配置

npm i react-app-rewired --dev
複製代碼

使用 babel-plugin-import實現按需加載

npm i babel-plugin-import --dev
複製代碼

使用react-app-rewire-less,經過 less 變量覆蓋功能自定義主題

npm i react-app-rewire-less --dev
複製代碼

antd 官網上須要咱們配置package.json中的scripts

/* package.json */
"scripts": {
-   "start": "react-scripts start",
+   "start": "react-app-rewired start",
-   "build": "react-scripts build",
+   "build": "react-app-rewired build",
-   "test": "react-scripts test --env=jsdom",
+   "test": "react-app-rewired test --env=jsdom",
}
複製代碼

可是咱們已經再也不使用react-scripts了,而是用了本身的配置,因此咱們去看一下react-app-rewired作了什麼 // 這裏我讀了react-app-rewired的代碼作了一些處理,至於使用,你只須要在項目根目錄建立一個 config-overrides.js 用於修改默認配置。

以下

const { injectBabelPlugin } = require('react-app-rewired');
const rewireLess = require('react-app-rewire-less');

 module.exports = function override(config, env) {
 config = injectBabelPlugin(['import', { libraryName: 'antd', style: 'css' }], config);
 config = injectBabelPlugin(['import', { libraryName: 'antd', style: true }], config);
 config = rewireLess.withLoaderOptions({
   modifyVars: { "@primary-color": "#1DA57A" },
 })(config, env);
   return config;
 };
複製代碼

在script的start.js和build.js裏添加:

// 自定義配置
  const overrides = require('../config-overrides');
  const webpackConfig = require('../config/webpack.config.dev');
  require.cache[require.resolve('../config/webpackDevServer.config.js')].exports =
    overrides(webpackConfig, process.env.NODE_ENV);

複製代碼

若是安裝中出現問題,建議使用yarn解決

具體實例參考個人github,歡迎交流指正 react-cli

相關文章
相關標籤/搜索