react+express項目

1 開發環境準備(windows)

1.1 安裝nodejs和npm

命令行輸入以下命令,查看npm和node版本:
npm -v
node -v

  若未安裝成功可檢查環境變量是否安裝時自動設置成功

1.2 安裝create-react-app(react官方提供的腳手架)

  命令行輸入:npm install -g create-react-app

create-react-app:可以用來快速創建react項目
-g:全局安裝create-react-app腳手架工具,這個步驟只需要執行一次

1.3 安裝express-generator(express官方提供腳手架)

  命令行輸入: npm install express-generator -g

express-generator:可以用來快速創建express應用
-g:全局安裝express-generator腳手架工具,這個步驟只需要執行一次

2 創建react+express項目

前端框架:react
服務端:基於node的express框架

  兩者結合快速創建web項目。由於服務端代碼需要部署到服務器,爲了方便操作,先創建react項目,然後在react項目目錄下創建express項目,將react的打包目錄設置爲express項目下的public文件。

(1)創建react項目(client)
create-react-app myapp
(2)創建express項目(server)
cd myapp
express-generator --view=ejs server 
添加模版引擎:--view=ejs,此處選擇ejs作爲模版引擎。還可以選擇pub、jade等其它模版引擎

2.2 react初始項目目錄結構

  使用create-react-app創建的項目,已經把webpack、babel等配置都封裝到依賴項目react-script中,因此在目錄外層無法看到webpack等配置文件。

  • 1)自動生成的項目目錄介紹

    • A. node_modules:項目依賴包目錄,使用npm install xxx相關命令安裝的依賴都會自動下載到該目錄,無需提交至git;
    • B. public:公共目錄,該目錄下的文件都不會被webpack進行加載、解析和打包;通過npm run build進行打包時該目錄下的所有文件將會直接被複制到build目錄下;

      • a) favicon.ico:網站圖標(可替換刪除)
      • b) index.html:頁面模板,webpack打包後將輸出文件引入到該模板內;index.html中通過環境變量%PUBLIC_URL%指向public目錄路徑;
      • c) manifest.json:PWA將應用添加至桌面的功能的實現依賴於manifest.json。通過manifest.json文件可以對
    • C. src: 是源碼目錄,該目錄下除了index.js App.test.js registerServiceWorker.js 文件具有一定意義其餘文件都是演示使用可直接刪除。

      • a) index.js: 是整個項目的入口文件,也是webpack打包的入口文件;
      • b) App.js:項目創建後,可通過修改此文件來修改頁面內容
      • c) App.test.js: 測試單元演示文件,暫時並不知道幹嘛用;可以直接刪除;
      • d) registerServiceWorker.js: service worker 是在後臺運行的一個線程,可以用來處理離線緩存、消息推送、後臺自動更新等任務;registerServiceWorker就是爲react項目註冊了一個service worker,用來做資源的緩存,這樣你下次訪問時,就可以更快的獲取資源。而且因爲資源被緩存,所以即使在離線的情況下也可以訪問應用(此時使用的資源是之前緩存的資源)。注意,registerServiceWorker註冊的service worker 只在生產環境中生效,並且該功能只有在https下纔能有效果;
    • D. .gitignore: 該文件是github過濾文件配置,即指定無需提交至git而忽略的文件,幫助查看方式,git help ignore
    • E. README.md: 該文件是描述文件
    • F. package.json: 定義了項目所需要的各種模塊,以及項目的配置信息(比如名稱、版本、許可證等元數據)。部分依賴模塊被隱藏;
    • G. package.lock.json: 每次通過npm添加依賴或者更新包版本時 npm都會把相關版本信息寫入package.lock.json文件;
  • 2)package.json配置

  • 3)可用腳本命令說明

首先說明:通過npm run 執行下面命令實際上是運行 node_modules/react-srcipt/script下對應的腳本文件;

  • A.npm run start : 開始項目,通過http://localhost:3000 可訪問項目;
  • B. npm run build : 項目打包,在生產環境中編譯代碼,並放在build目錄中;所有代碼將被正確打包,並進行優化、壓縮同時使用hash重命名文件;執行該命令前需要在package.json中新增條配置"homepage": "."(上面配置文件已給出), 同時build後的項目需要在服務器下才能訪問;否則打開的將是空白頁面;
  • C. npm run test : 交互監視模式下啓動測試運行程序;
  • D. npm run eject : 將隱藏的配置導出;需要知道的是create-react-app腳手架本質上是使用react-scripts進行配置項目,所有配置文件信息都被隱藏起來(node_modules/react-scripts);當需要手動修改擴展webpack配置時有時就需要將隱藏的配置暴露出來;特別需要注意的是該操作是一個單向操作,一旦使用eject,那麼就不能恢復了(再次將配置隱藏);

2.3 react項目配置

  create-react-app默認生成的是單入口單出口生產環境,統一通過react-script進行管理,無法滿足複雜的多入口項目的需要,因此需要對項目進行配置,使其滿足實際項目需要。可通過npm run eject來暴露所有內建配置,以方便我們對項目的配置進行修改。

2.3.1 npm run eject

  進入myapp根目錄,執行以下命令:npm run eject。暴露所有內建配置,項目下會新增或對部分配置文件進行修改。
  根目錄下新增config(配置文件)和script(腳本文件)目錄。

注意:此操作不可逆,一旦執行無法回退;
修改配置的其它方法:也可考慮採用react-app-rewired插件來實現配置覆蓋。
2.3.2 多入口配置
項目默認只有index.js(src目錄下)這一個入口文件。

以在src目錄下新增入口文件admin.js爲例。新增admin.js入口文件
需修改config中的配置文件來:

  • 1)修改webpcak.config.dev.js文件
  • A. 修改entry(新增js文件入口配置)
//這裏我已經寫成對象格式了
//有多少個頁面就添加多少個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',
        ]
    }

修改entry

  • B. 修改plugins中的HtmlWebpackPlugin(配置html模版文件)
//多少個頁面就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'
    }),
  • C.修改output
//由於原配置入口文件只有一個,因此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, '/'),
 },
  • 2) 修改config下webpack.config.prod.js文件
  • A 修改entry
//這裏的paths.appIndexJs和paths.appSrc+'/admin.js'是入口文件
    entry:{
        index:[
            require.resolve('./polyfills'), 
            paths.appIndexJs
        ],
        admin:[
            require.resolve('./polyfills'),
            paths.appSrc+'/admin.js'
        ]
    }
  • B 修改plugins中的HtmlWebpackPlugin
//和開發環境下一樣,多少個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,
      },
    }),
  • 3)在開發環境中如果想通過地址訪問不同頁面,需要修改webpackDevServer.config.js
  • A 修改historyApiFallback
//這裏的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' },
      ]
    },
2.3.3 前端跨域問題配置
生產環境:本文中的項目,由於打包後的代碼會放在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
     }
 }
2.3.4 文件路徑簡化配置

  當頁面嵌套過深時,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'

缺點:此方法能簡化引用方法,但無法通過快捷鍵進入該引用文件。
2.3.5 webpack打包體積詳情分佈
  • 1)安裝:npm install –save-dev webpack-bundle-analyzer
  • 2)配置:
//修改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”
  • 3)運行npm run buildnpm run analyz瀏覽器會自動打開127.0.0.1:8888,如下頁面,可查看打包後文件分佈,以及打包文件大小。

2.3.6 webpack構建打包優化
  • 1)使用UglifyJSPlugin壓縮js文件

安裝方法: npm install uglifyjs-webpack-plugin --save-dev 

在webpack.config.prod.js文件中添加
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
module.exports = {
    plugins: [
           new UglifyJSPlugin(),
     ]
}
  • 2)生產環境去掉map文件:縮短build時間
//修改webpack.config.prod.js文件:
//註釋devtool:shouldUseSourceMap? 'source-map':false
devtool:false,//增加
  • 3)添加cache-loader,減少打包時間
//修改webpack.config.dev.js文件:
module:{
    rules:[{
      use:[
              //添加在最前面
          'cache-loader', 
      ]
    }]
}
在其它加載程序加載之前添加以將結果緩存在磁盤上
  • 4)提取公共包:提取多個入口引入的公共依賴包

修改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,    },}),
2.3.7 build命令

  命令行輸入:npm run build,出現以下文件夾,其中admin.html和index.html分別是不同的入口。

2.3.8 修改build後資源文件根路徑

  可在path.js文件中修改打包後資源文件路徑,例如修改path.js文件中getServedPath方法中的‘/’,改爲‘/build’,則打包後資源文件的路徑會加上build,修改前資源文件路徑中是沒有build的。

  本文中react+express的項目,無需修改資源文件根路徑,因爲express會配置資源文件所在目錄爲。

2.4 express項目配置(與react結合)

2.4.1 nodemon熱啓動

  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"
2.4.2 react打包目錄相關修改

  爲了方便,將react打包目錄修改爲server目錄下public目錄,可以避免每次打包後都需要將build目錄下的文件在複製到server目錄下。

//修改path.js文件,module.exports中的appBuild變量
//將appBuild: resolveApp('build'),改爲
appBuild: resolveApp('server/public'),
2.4.3 在react的package.json中增加server的啓動命令

  在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"
  },

2.5 react開發調試工具

2.5.1 react-developer-tools

  瀏覽器擴展工具中搜索此插件並安裝,可以查看到react組件結構

2.5.2 chrome下的source map

  chrome引入了source-map文件,可以查看打包前代碼。唯一要做的就是配置webpack自動生成source-map文件,這也很簡單,在webpack.config.js中增加一行配置即可(需要重新啓動webpack-dev-server使配置生效),create-react-app已做此配置,因此不需要再修改。

2.5.3 Eslint(javascript代碼檢查工具)

  Create-react-app已安裝Eslint,可對eslint進行自定義配置規則。

2.6 項目目錄結構優化

2.6.1 react項目目錄結構優化

  開發目錄主要是src目錄,因此需要修改的目錄主要是src目錄。

|——src
|————|common //公共組件目錄,如http.js、cookie.js等
|————|components //基礎組件、業務組件、業務代碼抽象出的一些基礎類,例如每個頁面可以在此目錄下建立一個文件存放相關組件。
|————|layouts //佈局相關組件及其樣式文件,如header.js、footer.js、menu.js等
|————|styles //公共樣式文件
|————|static //公共的靜態資源文件,如公共的圖片資源文件等
|————|views //頁面入口文件,可與comonents中的頁面組件對應

如果使用了router和redux可在src下增加目錄:

  • redux:redux應用數據狀態管理文件,包括actions、reducers、stores三個子目錄
  • routes:路由管理模塊
  • containers:應用根容器,用於連接redux和router

2.6.2 express項目目錄結構優化
|——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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章