1) 下載nodejs安裝包:http://nodejs.org/en/download/javascript
nodejs安裝時會同時安裝npm
命令行輸入如下命令,查看npm和node版本:
npm -v
node -v
若未安裝成功可檢查環境變量是否安裝時自動設置成功css
命令行輸入:npm install -g create-react-app
html
create-react-app:能夠用來快速建立react項目
-g:全局安裝create-react-app腳手架工具,這個步驟只須要執行一次
命令行輸入: npm install express-generator -g
前端
express-generator:能夠用來快速建立express應用
-g:全局安裝express-generator腳手架工具,這個步驟只須要執行一次
前端框架:react
服務端:基於node的express框架
二者結合快速建立web項目。因爲服務端代碼須要部署到服務器,爲了方便操做,先建立react項目,而後在react項目目錄下建立express項目,將react的打包目錄設置爲express項目下的public文件。java
create-react-app myapp
cd myapp express-generator --view=ejs server
添加模版引擎:--view=ejs,此處選擇ejs做爲模版引擎。還能夠選擇pub、jade等其它模版引擎
使用create-react-app建立的項目,已經把webpack、babel等配置都封裝到依賴項目react-script中,所以在目錄外層沒法看到webpack等配置文件。node
1)自動生成的項目目錄介紹react
B. public:公共目錄,該目錄下的文件都不會被webpack進行加載、解析和打包;經過npm run build進行打包時該目錄下的全部文件將會直接被複制到build目錄下;webpack
C. src: 是源碼目錄,該目錄下除了index.js App.test.js registerServiceWorker.js 文件具備必定意義其他文件都是演示使用可直接刪除。git
首先說明:經過npm run 執行下面命令其實是運行 node_modules/react-srcipt/script下對應的腳本文件;github
create-react-app默認生成的是單入口單出口生產環境,統一經過react-script進行管理,沒法知足複雜的多入口項目的須要,所以須要對項目進行配置,使其知足實際項目須要。可經過npm run eject來暴露全部內建配置,以方便咱們對項目的配置進行修改。
進入myapp根目錄,執行如下命令:npm run eject
。暴露全部內建配置,項目下會新增或對部分配置文件進行修改。
根目錄下新增config(配置文件)和script(腳本文件)目錄。
注意:此操做不可逆,一旦執行沒法回退;
修改配置的其它方法:也可考慮採用react-app-rewired插件來實現配置覆蓋。
項目默認只有index.js(src目錄下)這一個入口文件。
以在src目錄下新增入口文件admin.js爲例。
需修改config中的配置文件來:
//這裏我已經寫成對象格式了 //有多少個頁面就添加多少個key:value //這裏我已經添加了一個admin //數組中的paths.appSrc+'/admin.js'就是這個html頁面的入口文件 entry: { index:[ require.resolve('./polyfills'), require.resolve('react-dev-utils/webpackHotDevClient'), paths.appIndexJs, ], admin:[ require.resolve('./polyfills'), require.resolve('react-dev-utils/webpackHotDevClient'), paths.appSrc + '/admin.js', ] }
//多少個頁面就new 多少個 HtmlWebpackPlugin //而且在每個裏面的chunks都須要和上面的entry中的key匹配 //例如上面entry中有index和admin這兩個。 //這裏的chunks也須要是index和admin new HtmlWebpackPlugin({ inject: true, chunks:["index"], template: paths.appHtml, }), new HtmlWebpackPlugin({ inject: true, chunks:["admin"], template:paths.appHtml, filename:'admin.html' }),
//因爲原配置入口文件只有一個,所以output中的filename是寫死的, //增長多入口以後,輸出文件名被寫死,對應生成了多個boundle.js, //後面生成的會覆蓋前面生成的文件,因此須要制定輸出的文件名不能寫死 output: { path:paths.appBuild, pathinfo: true, filename: 'static/js/[name].bundle.js', chunkFilename: 'static/js/[name].chunk.js', publicPath: publicPath, devtoolModuleFilenameTemplate: info => path.resolve(info.absoluteResourcePath).replace(/\\/g, '/'), },
//這裏的paths.appIndexJs和paths.appSrc+'/admin.js'是入口文件 entry:{ index:[ require.resolve('./polyfills'), paths.appIndexJs ], admin:[ require.resolve('./polyfills'), paths.appSrc+'/admin.js' ] }
//和開發環境下同樣,多少個html就new多少個 HtmllWebpackPlugin,每一個都須要指定chunks,而且指定filename,在minify中配置是否壓縮js、css等,這是生產環境下的配置 new HtmlWebpackPlugin({ inject: true, chunks:["index"], template: paths.appHtml, minify: { removeComments: true, collapseWhitespace: true, removeRedundantAttributes: true, useShortDoctype: true, removeEmptyAttributes: true, removeStyleLinkTypeAttributes: true, keepClosingSlash: true, minifyJS: true, minifyCSS: true, minifyURLs: true, }, }), new HtmlWebpackPlugin({ inject: true, chunks:["admin"], template: paths.appHtml, filename:'admin.html', minify: { removeComments: true, collapseWhitespace: true, removeRedundantAttributes: true, useShortDoctype: true, removeEmptyAttributes: true, removeStyleLinkTypeAttributes: true, keepClosingSlash: true, minifyJS: true, minifyCSS: true, minifyURLs: true, }, }),
//這裏的rewrites:[ {from: /^\/admin.html/, to: '/build/admin.html' }] 數組裏面是一個個對象, //對象中前面的值是在開發時候訪問的路徑,例如 npm run start以後會監聽 localhost:3000 , //此時在後面加上 /admin.html就會訪問admin.html中的內容,默認是訪問index.html; //數組中的第二個值是生產環境下的文件的路徑。 //若是有不少頁面,就在rewrites中添加更多對象 historyApiFallback: { disableDotRule: true, rewrites: [ { from: /^\/admin.html/, to: '/build/admin.html' }, ] },
生產環境:本文中的項目,因爲打包後的代碼會放在server目錄下的public文件夾下,也就是打包後的代碼和server在同域下,不存在跨域問題。
開發環境:開發時,前端react項目和後端express項目運行時端口端口不一樣,存在跨域問題。
開發環境跨域問題解決辦法:在package.json中加入:"proxy":http://localhost:5000 //後端所在域
。
若是須要後端存在多個域:
//package.json中加入 "proxy": { "/api1": { "target": "http://api1.xxxx.com", "changeOrigin":true }, "/api2":{ "target":"http://api2.xxxx.com", "changeOrigin":true } }
當頁面嵌套過深時,import Apis from '../../common/apis',可經過webpack配置來簡化路徑。
//修改webpack.config.dev與webpack.config.prod兩個文件,加入相同配置 //增長方法 function resolve(dir) { return path.join(__dirname, '..', dir) } //修改 alias配置 alias: { 'react-native': 'react-native-web', //加入配置 '@src': resolve('src') }
添加上述配置後,引入文件方式:import Apis from '@src/common/apis'
缺點:此方法能簡化引用方法,但沒法經過快捷鍵進入該引用文件。
//修改webpack.prod.conf.js文件,增長以下內容 const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; module.exports = { plugins: [ new BundleAnalyzerPlugin() ] } //修改package.json文件,在scripts中增長以下命令 「analyz」: 「NODE_ENV=production npm_config_report=true npm run build」
npm run build
或npm run analyz
,瀏覽器會自動打開127.0.0.1:8888,以下頁面,可查看打包後文件分佈,以及打包文件大小。
安裝方法: npm install uglifyjs-webpack-plugin --save-dev
在webpack.config.prod.js文件中添加 const UglifyJsPlugin = require('uglifyjs-webpack-plugin') module.exports = { plugins: [ new UglifyJSPlugin(), ] }
//修改webpack.config.prod.js文件: //註釋devtool:shouldUseSourceMap? 'source-map':false devtool:false,//增長
//修改webpack.config.dev.js文件: module:{ rules:[{ use:[ //添加在最前面 'cache-loader', ] }] }
在其它加載程序加載以前添加以將結果緩存在磁盤上
修改webpack.config.prod.js文件
//修改entry文件, entry: //這裏的paths.appIndexJs和paths.appSrc+'/admin.js'依然是每一個html的入口文件 { index:[ require.resolve('./polyfills'), paths.appIndexJs, ], admin:[ require.resolve('./polyfills'), paths.appSrc+'/admin.js' ], //增長vendor vendor:['react','react-dom'] }, //修改plugin plugin:{ //新增如下代碼 new webpack.optimize.CommonsChunkPlugin({ name: ["vendor"], // filename:'static/js/vendor.[chunkhash:8].js', // minChunks: 3 //三方庫在邏輯代碼中被調用兩次(數字能夠自定義), 將公共的代碼提取出來 }), /* 防止 vendor hash 變化 */ // extract webpack runtime and module manifest to its own file in order to // prevent vendor hash from being updated whenever app bundle is updated new webpack.optimize.CommonsChunkPlugin({ name: 'manifest', chunks: ['vendor'] }), } //修改plugins中的HtmlWebpackPlugin,在chunks中添加須要引入的公共包, //其中公共包需放在後面,使其在加入html頁面時能在其它js文件前面 new HtmlWebpackPlugin({ inject: true, chunks:["index","vendor"], template: paths.appHtml, minify: { removeComments: true, collapseWhitespace: true, removeRedundantAttributes: true, useShortDoctype: true, removeEmptyAttributes: true, removeStyleLinkTypeAttributes: true, keepClosingSlash: true, minifyJS: true, minifyCSS: true, minifyURLs: true, },}),new HtmlWebpackPlugin({ inject: true, chunks:["admin","vendor"], template: paths.appHtml, filename:'admin.html', minify: { removeComments: true, collapseWhitespace: true, removeRedundantAttributes: true, useShortDoctype: true, removeEmptyAttributes: true, removeStyleLinkTypeAttributes: true, keepClosingSlash: true, minifyJS: true, minifyCSS: true, minifyURLs: true, },}),
命令行輸入:npm run build
,出現如下文件夾,其中admin.html和index.html分別是不一樣的入口。
可在path.js文件中修改打包後資源文件路徑,例如修改path.js文件中getServedPath方法中的‘/’,改成‘/build’,則打包後資源文件的路徑會加上build,修改前資源文件路徑中是沒有build的。
本文中react+express的項目,無需修改資源文件根路徑,由於express會配置資源文件所在目錄爲。
express框架中啓動項目後,文件更新後須要手動重啓node服務,修改纔會生效。使用nodemon能夠實現熱啓動,文件修改後自動重啓使修改生效。
在server根目錄(express項目根目錄)下運行如下命令,安裝nodemon:npm --save-dev install nodemon
//修改server(express項目根目錄)目錄下的package.json文件,將node改成nodemon //將"start":"node ./bin/www"改成: "start":"nodemon ./bin/www"
爲了方便,將react打包目錄修改成server目錄下public目錄,能夠避免每次打包後都須要將build目錄下的文件在複製到server目錄下。
//修改path.js文件,module.exports中的appBuild變量 //將appBuild: resolveApp('build'),改成 appBuild: resolveApp('server/public'),
在webstorm中,會自動出現根目錄下package.json中的scripts下的npm命令,爲了方便啓動server,可在react 根目錄下的package.json文件中增長server的啓動項。
"scripts": { "start": "node scripts/start.js", "server-start": "cd server && npm run start",//增長server啓動命令 "build": "node scripts/build.js", "test": "node scripts/test.js" },
瀏覽器擴展工具中搜索此插件並安裝,能夠查看到react組件結構
chrome引入了source-map文件,能夠查看打包前代碼。惟一要作的就是配置webpack自動生成source-map文件,這也很簡單,在webpack.config.js中增長一行配置便可(須要從新啓動webpack-dev-server使配置生效),create-react-app已作此配置,所以不須要再修改。
Create-react-app已安裝Eslint,可對eslint進行自定義配置規則。
開發目錄主要是src目錄,所以須要修改的目錄主要是src目錄。
|——src |————|common //公共組件目錄,如http.js、cookie.js等 |————|components //基礎組件、業務組件、業務代碼抽象出的一些基礎類,例如每一個頁面能夠在此目錄下創建一個文件存放相關組件。 |————|layouts //佈局相關組件及其樣式文件,如header.js、footer.js、menu.js等 |————|styles //公共樣式文件 |————|static //公共的靜態資源文件,如公共的圖片資源文件等 |————|views //頁面入口文件,可與comonents中的頁面組件對應
若是使用了router和redux可在src下增長目錄:
|——server // express項目根目錄 |————|bin |——————|www //服務器相關配置文件 |————|controllers //控制器層,處理前端請求 |————|models //數據庫操做相關文件 |————|node_modules //npm包安裝目錄 |————|public //react打包目錄,存放全部的html,js/css/圖片等資源文件 |————|routes // 路由文件目錄 |——————|api.js //api請求路由文件 |——————|pages.js // 頁面請求路由文件 |————|utils // 公共文件目錄 |——————|config.js //各類常量或公共方法 |——————|db.js // 數據庫訪問方法封裝 |——————|http.js //http請求方法封裝 |————|views // express框架自帶,因爲打包後的文件全放在public目錄下,所以這個文件可不用了 |————|app.js //入口文件 |————|package.json |————|package-lock.json