本文主要是對SPA搭建的實踐過程講解,在對react、redux、react-router有了初步瞭解後,來運用這些技術構建一個簡單的單頁應用。這個應用包括了側邊導航欄與主體內容區域。下面簡單羅列了將會用到的一些框架與工具。javascript
function
(而不只僅是object
),而且使得dispatch方法能夠接收一個function
做爲參數,經過這種改造使得action支持異步(或延遲)操做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是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