使用 create-react-app 構建 react應用程序

本文主要是對SPA搭建的實踐過程講解,在對react、redux、react-router有了初步瞭解後,來運用這些技術構建一個簡單的單頁應用。這個應用包括了側邊導航欄與主體內容區域。下面簡單羅列了將會用到的一些框架與工具。javascript

  • create-react-app:腳手架
  • react:負責頁面組件構建
  • react-router:負責單頁應用路由部分的控制
  • redux:負責管理整個應用的數據流
  • react-redux:將react與redux這兩部分相結合
  • redux-thunk:redux的一箇中間件。可使action creator返回一個function(而不只僅是object),而且使得dispatch方法能夠接收一個function做爲參數,經過這種改造使得action支持異步(或延遲)操做
  • redux-actions:針對redux的一個FSA工具箱,能夠相應簡化與標準化action與reducer部分

create-react-app 是一個全局的命令行工具用來建立一個新的項目css

react-scripts 是一個生成的項目所須要的開發依賴

  
      通常咱們開始建立react web應用程序的時候,要本身經過 npm 或者 yarn 安裝項目的所有依賴,再寫webpack.config.js,一系列複雜的配置,搭建好開發環境後寫src源代碼。
如今 若是你正在搭建react運行環境,使用 create-react-app 去自動構建你的app程序。你的項目所在的文件夾下是沒有配置文件。react-scripts 是惟一的 額外的 構建依賴在你的package.json中,你的運行環境將有每個你須要用來構建一個現代React app應用程序。你須要的依賴,和在配置文件中編寫的配置代碼,react-scripts 都幫你寫了,好比:react-scripts幫你自動下載須要的 webpack-dev-server 依賴,而後react-scripts本身寫了一個nodejs服務端的腳本代碼 start.js來 實例化 WebpackDevServer ,而且運行啓動了一個使用 express 的Http服務器,如今你只須要專心寫src源代碼就能夠了。省去了不少精力,最適合快速上手一個demo了。

react-scripts有如下支持,都幫你配置好了:
React, JSX, ES6, and Flow syntax support.
Language extras beyond ES6 like the object spread operator.
Import CSS and image files directly from JavaScript.
Autoprefixed CSS, so you don’t need -webkit or other prefixes.
A build script to bundle JS, CSS, and images for production, with sourcemaps.
A dev server that lints for common errors.html

使用create-react-app腳手架

create-react-app是Facebook官方出品的腳手架。有了它,你只須要一行指令便可跳過webpack繁瑣的配置、npm繁多的引入等過程,迅速構建react項目。java

安裝

npm install -g create-react-app

建立一個應用程序 

create-react-app my-app  
cd my-app

生成的目錄結構

my-app/  
  README.md  
  node_modules/  
  package.json  
  .gitignore  
  public/  
    favicon.ico  
    index.html  
  src/  
    App.css  
    App.js  
    App.test.js  
    index.css  
    index.js  
    logo.svg

運行應用程序

npm run start

在瀏覽器中打開

http://localhost:3000

如今咱們看 my-app文件夾下的public/index.html 和src/index.js的源碼,咱們能夠在這裏編寫項目代碼,可是注意 public/index.html 是啓動http服務器的首頁,src/index.js是編譯的入口文件,只能叫index這個名字,改別的名字不行。
打開 http://localhost:3000/index.html 首頁,f12查看 網頁源碼,你會看到 node

<script type="text/javascript" src="/static/js/bundle.js"></script>

/static/js/bundle.js
在你的項目my-app你是看不到這個文件路徑的,你也沒有寫配置文件webpack.config.js,
http服務器配置,自動代開瀏覽器窗口,react,es6語法編譯,babel-core,webpack,等等這些 你都沒下載,配置。
這些活,react-scripts 都幫你作了。react

回顧 
npm run start
咱們 一開始這麼啓動服務 運行項目
打開你的my-app\package.jsonwebpack

"scripts": {  
    "start": "react-scripts start",  
      ...  
  }

因此執行的是 react-scripts start 
打開你的my-app\node_modules\react-scripts這個文件夾下的bin文件夾下的react-scripts.js文件git

#!/usr/bin/env node  
var spawn = require('cross-spawn');  
var script = process.argv[2];  
var args = process.argv.slice(3);  
  
switch (script) {  
case 'build':  
case 'eject':  
case 'start':  
case 'test':  
  var result = spawn.sync(  
    'node',  
    [require.resolve('../scripts/' + script)].concat(args),  
  .......

上面代碼中  script 的變量值是 start
因此執行 my-app\node_modules\react-scripts\scripts 文件夾下的  start.js 文件代碼節選重點以下es6

var webpack = require('webpack');  
var WebpackDevServer = require('webpack-dev-server');  // 啓動http服務器  
var paths = require('../config/paths');  //要編譯的文件路徑與生成路徑等  
var config = require('../config/webpack.config.dev');  
var DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000; //這就是爲何 端口號 不是8080 而是 3000 的緣由,在這裏能夠改爲8080,從新npm run start 生效   
detect(DEFAULT_PORT).then(port => {  
  if (port === DEFAULT_PORT) {  
    run(port); //這裏開始運行  
    return;  
  }  
......  
  
function run(port) {   
// 這裏能夠設置 http協議, 或者能夠在 npm run start 以前 cmd命令窗口中執行 set HTTPS=true&&npm start 改爲https 安全協議  
  var protocol = process.env.HTTPS === 'true' ? "https" : "http";   
  var host = process.env.HOST || 'localhost';     
  setupCompiler(host, port, protocol);  // 編譯源碼 ,生成路徑  
  runDevServer(host, port, protocol);  //啓動 http服務器  
}  
  
  
//配置http服務器  
function runDevServer(host, port, protocol) {  
  var devServer = new WebpackDevServer(compiler, {  
   compress: true,     
    clientLogLevel: 'none',  
    contentBase: paths.appPublic,   //根據導入的paths 指定應用根目錄(即index.html所在目錄)  
    hot: true,  
  
    publicPath: config.output.publicPath, //根據導入的 config 變量,指定 虛擬目錄,自動指向path編譯目錄(/assets/ => /build/js/)。html中引用js文件時,  
                                             //必須引用此虛擬路徑(但實際上引用的是內存中的文件,既不是/build/js/也不是/assets/)。  
   
    quiet: true,  
  
  
    watchOptions: {  
      ignored: /node_modules/  
    },  
    // Enable HTTPS if the HTTPS environment variable is set to 'true'  
    https: protocol === "https",  
    host: host  
  });  
  /**  
   * 省略其餘代碼  
   */  
    openBrowser(protocol + '://' + host + ':' + port + '/');    // 打開瀏覽器 向服務器發送請求  
  });  
}  
  
  
function setupCompiler(host, port, protocol) {  
  
  compiler = webpack(config, handleCompile);  //  根據導入的 config 變量  指向的 webpack.config.dev 配置文件  運行  
     /**  
   * 省略其餘代碼  
   */  
}

 start.js 文件代碼 中 導入了  my-app\node_modules\react-scripts\config文件夾下的  webpack.config.dev.js 與 paths.js
paths.js  代碼節選以下:github

var appDirectory = fs.realpathSync(process.cwd());   // 獲取npm run start 運行所在的路徑  
function resolveApp(relativePath) {  
  return path.resolve(appDirectory, relativePath);  
}  
  
module.exports = {  
  appPath: resolveApp('.'),  
  ownPath: resolveApp('node_modules/react-scripts'),  
  appBuild: resolveApp('build'),  
  appPublic: resolveApp('public'),  
  appHtml: resolveApp('public/index.html'),   //  這就是  一開始  咱們的項目 要使用public/index.html做爲 默認首頁   
                //  這裏寫什麼文件名,項目中就要使用什麼文件名  包括 也要有public文件夾  
  appIndexJs: resolveApp('src/index.js'),   //編譯的入口文件的文件名  項目中要包括src文件夾  
  appPackageJson: resolveApp('package.json'),  
  appSrc: resolveApp('src'),  
  yarnLockFile: resolveApp('yarn.lock'),  
  testsSetup: resolveApp('src/setupTests.js'),  
  appNodeModules: resolveApp('node_modules'),  
  // this is empty with npm3 but node resolution searches higher anyway:  
  ownNodeModules: resolveOwn('node_modules'),  
  nodePaths: nodePaths,  
  publicUrl: getPublicUrl(resolveApp('package.json')),  
  servedPath: getServedPath(resolveApp('package.json'))  
};  
 /**  
   * 省略其餘代碼  
   */

webpack.config.dev.js  代碼節選以下:

var paths = require('./paths');  //也導入了 同文件夾下的 paths.js  
module.exports = {  entry: [    require.resolve('react-dev-utils/webpackHotDevClient'),    require.resolve('./polyfills'),    paths.appIndexJs     // 編譯的入口文件  ],  output: {    path: paths.appBuild,    pathinfo: true,       filename: 'static/js/bundle.js', // 只是編譯後生成的目標文件 ,這就是一開始咱們 打開瀏覽器按f12看到的index.html導入的           //  <script type="text/javascript" src="/static/js/bundle.js"></script>    publicPath: publicPath  },  
 /**  
   * 省略其餘代碼  
   */  
  
}

已經搭建好運行環境了,接下來 如何開發app

導入組件

因爲babel依賴,這個項目支持es6模塊
當你仍然使用require() and module.exports ,咱們鼓勵你去使用import and export 替代.
例如: 
Button.js

import React, { Component } from 'react';  
  
class Button extends Component {  
  render() {  
    // ...  
  }  
}  
export default Button; // 不要忘記去使用 export default!

DangerButton.js

import React, { Component } from 'react';  
import Button from './Button'; //從另外一個文件導入一個組件  
  
  
class DangerButton extends Component {  
  render() {  
    return <Button color="red" />;  
  }  
}  
export default DangerButton;

增長樣式
Button.css

.Button {  
  padding: 20px;  
}

Button.js

import React, { Component } from 'react';  
import './Button.css'; // 告訴webpack Button.js 使用這些樣式  
  
  
class Button extends Component {  
  render() {  
    // You can use them as regular CSS styles  
    return <div className="Button" />;  
  }  
}

Autoprefixer

react-scripts 經過Autoprefixer 幫你的css文件自動添加瀏覽器兼容前綴
例如:

.App {  
  display: flex;  
  flex-direction: row;  
  align-items: center;  
}

變成

.App {  
  display: -webkit-box;  
  display: -ms-flexbox;  
  display: flex;  
  -webkit-box-orient: horizontal;  
  -webkit-box-direction: normal;  
      -ms-flex-direction: row;  
          flex-direction: row;  
  -webkit-box-align: center;  
      -ms-flex-align: center;  
          align-items: center;  
}

增長CSS預處理器

首先在 my-app/  目錄下  安裝node-sass用來將scss編譯成css

npm install node-sass --save-dev

打開my-app/package.json,增長如下代碼到scripts中

"scripts": {  
+    "build-css": "node-sass src/ -o src/",  
+    "watch-css": "npm run build-css && node-sass src/ -o src/ --watch",  
     "start": "react-scripts start",  
     "build": "react-scripts build",  
     ......  
    }

如今你能夠從新命名my-app/src/App.css to my-app/src/App.scss and 運行   npm run watch-css
或者你能夠改爲

"scripts": {  
    "build-css": "node-sass src/ -o src/",  
    "start": "npm run build-css && react-scripts start",  //先執行 build-css 再執行 react-scripts start  
    "build": "react-scripts build",  
    "test": "react-scripts test --env=jsdom",  
    "eject": "react-scripts eject"  
  }

直接 npm run start

增長圖片

import React from 'react';  
import logo from './logo.png'; // 告訴webpack 這個js文件使用這張圖片  
  
console.log(logo); // /logo.84287d09.png  會改變圖片的名字  
  
function Header() {  
  //導入結果是這個圖片的url地址  
  return <img src={logo} alt="Logo" />;  
}  
  
export default Header;

當項目構建的時候,Webpack將正確的移動圖片到構建的文件夾下,提供咱們正確的路徑

在css工做中的方式也同樣

.Logo {  
  background-image: url(./logo.png);  
}

webpack發現全部的相對模塊, 以 ./  開始

增長 bootstrap
在react+es6 moudle+bootstrap
你不是必定要React Bootstrap和React 一塊兒使用,可是他是流行的庫去整合 bootstrap 和react應用程序,若是你須要他,你能夠經過Create React App整合他,經過如下幾個步驟

首先安裝React Bootstrap and Bootstrap從npm,React Bootstrap 不包括Bootstrap CSS ,因此你須要去安裝
在 my-app/  目錄下  安裝

npm install react-bootstrap --save  
npm install bootstrap@3 --save

修改 my-app/src/index.js

在你的src/index.js 文件內容的頂部,導入 Bootstrap CSS 和可選的 Bootstrap theme CSS

import React from 'react';  
import ReactDOM from 'react-dom';  
import 'bootstrap/dist/css/bootstrap.css';  // 必須的  
import 'bootstrap/dist/css/bootstrap-theme.css';  //  可選的  
import App from './App';  
import './index.css';  
  
ReactDOM.render(  
  <App />,  
  document.getElementById('root')  
);

修改 my-app/src/App.js

import React, { Component } from 'react';  
import { Grid, Navbar, Jumbotron, Button } from 'react-bootstrap';  
  
class App extends Component {  
  render() {  
    return (  
      <div>  
        <Navbar inverse fixedTop>  
          <Grid>  
            <Navbar.Header>  
              <Navbar.Brand>  
                <a href="/">React App</a>  
              </Navbar.Brand>  
              <Navbar.Toggle />  
            </Navbar.Header>  
          </Grid>  
        </Navbar>  
        <Jumbotron>  
          <Grid>  
            <h1>Welcome to React</h1>  
            <p>  
              <Button  
                bsStyle="success"  
                bsSize="large"  
                href="http://react-bootstrap.github.io/components.html"  
                target="_blank">  
                View React Bootstrap Docs  
              </Button>  
            </p>  
          </Grid>  
        </Jumbotron>  
      </div>  
    );  
  }  
}  
  
export default App;

最後 運行

npm run start

參考連接 https://github.com/facebookincubator/create-react-app

參考資料:https://blog.csdn.net/github_squad/article/details/57452333

相關文章
相關標籤/搜索