react 項目構建

寫在前面

每次構建react項目的時候都會配置一大堆東西,時間久了就會忘記怎麼配置。爲了方便本身記憶也爲了其餘開發者在構建react應用時可以快速開發,故做此記錄。css

本項目基於 create-react-app 腳手架進行配置。主要配置了一些項目開發中經常使用的方法,好比 webpack的 sassredux熱加載代理以及其餘工具庫的引入等等。

初始化項目

首先,要先利用create-react-app建立一個react項目,可參考 https://github.com/facebookin...html

安裝 create-react-app前端

npm install -g create-react-app

建立一個應用程序node

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

注:my-app是指項目的名稱,用戶能夠自定義項目名稱react

這個時候能夠在命令行輸入 webpack

npm start : 啓動項目就能看到項目啓動頁面了。git

圖片描述

npm run build : 項目發佈。github

這樣一個簡單的react項目就初始化完畢了。web

可是,默認全部配置是隱藏起來的,要想自定義配置,須要運行一個命令:npm run eject
此時會提示,該命令不可逆,是否繼續,輸入y,這樣全部配置項就都出來了。會生成一個config文件夾,這時候也能夠作一些定製化的配置了。npm

項目配置

兼容IE

引入element-react UI框架會報錯 ReferenceError: 「Symbol」未定義

  • 解決方案:

項目中引入babel-polyfill,在app.js中導入便可

配置webpack

基於webpack的一些配置

配置sass

腳手架默認沒有配置sass,項目中若是使用sass須要單獨配置

一、安裝依賴 npm install --save-d node-sass sass-loader
二、修改config下面的webpack.config.dev.jswebpack.config.prod.js,都須要修改,開發環境和發佈環境是單獨的配置。

修改cssloader
test: /\.css$/, 修改成: test: /\.(css|scss|sass)$/,即識別scss/sass文件

最後添加
sass-loader

圖片描述

配置別名

別名在項目中方便咱們快速引入文件。好比咱們項目中有一個公共文件目錄爲src/util/tools,例若有如下文件結構

├── src                                   
│   ├── assets                            # 項目資源
│   │   └── ...
│   ├── containers                        # 頁面容器
│   │   └── pages
│   │       └── pageA                     # 頁面A     
│   │           └───a.js                  # a.js           
│   │── utils                             # 其餘工具類
│   │   └── tools
│   ├── index.js                          # webpack打包入口文件

在層級很深的組件內部a.js須要引入tools文件,咱們會使用../../../util/tools去找到文件的相對位置,可是在使用webpack配置的別名後能夠直接定位到/src目錄下。

// 未使用別名
import tools from '../../../util/tools';

// 使用別名後
import tools from '@/util/tools';  // '@/' 指向 'src/'

配置方式

dev和prod環境都須要配置

在resolve/alias進行配置

其中 resolve 是一個自定義函數。

function resolve(dir) {
    return path.join(__dirname, '..', dir)
}

也能夠寫成

'@': path.join(__dirname, '..', 'src')

圖片描述

配置熱加載

create-react-app項目中配置的有熱加載,咱們只須要在項目入口文件index.js中啓用熱加載就行,直接在末尾添加

// index.js
/* 熱加載 */
if (module.hot) {
  module.hot.accept();
}

圖片描述

配置代理服務器

在前端開發中請求接口常常會遇到跨域的問題,處理跨域的方式有不少,多數webpack是配置dev_server,但這種方法在create-react-app 生成的應用中無效,對於這種應用應在package.json處進行代理

// package.json
"proxy": "http://api.enjoycut.com/"

// 或者
"proxy": {
    "/article": {
      "target": "http://api.enjoycut.com/",
      "changeOrigin": true,
      "secure": false
    }
  }
// 下面的方式沒有配置過

配置路由

react-router4的使用方式和之前的router版本使用方式不一樣

react-router4文檔地址

配置redux

配置 @connect裝飾器

在項目中能夠直接經過@connect方式訪問redux

未配置
圖片描述

配置後

圖片描述

須要說明的是,這裏用了裝飾器,須要安裝模塊babel-plugin-transform-decorators-legacy

而後在package.json裏面配置plugins

圖片描述

項目中其餘工具配置

classnames

在react 中切換className比較麻煩,簡單的可使用三目運算,可是複雜一點的class就比較麻煩了,好比這個稍微複雜點的div動態切換多個className, 推薦一個工具庫,能夠簡單方便的切換className.

clsssnames使用文檔

圖片描述

<div className={classNames('clip_item', {
      'clip_active': isActive, 
      'effect_hover': activeDrag === 'video_inner',
       'dragging': is_dragging}
       )}>
      // 默認classNAme: 'clip_item'
      // isActive    === true 則添加className 'clip_active'
      // is_dragging === true 則添加className 'dragging'

moment

在項目中格式化時間的工具庫,將時間格式化成你想要的任何格式!很是方便。

moment().format('MMMM Do YYYY, h:mm:ss a'); // 九月 10日 2018, 7:04:30 晚上
moment().format('dddd');                    // 星期一
moment().format("MMM Do YY");               // 9月 10日 18
moment().format('YYYY [escaped] YYYY');     // 2018 escaped 2018
moment().format();                          // 2018-09-10T19:04:30+08:00

moment.js文檔地址:http://momentjs.cn/


項目後期優化

antd按需加載

通常狀況下,咱們按照antd官網使用方式在css中導入整個ui的樣式,@import '~antd/dist/antd.css';
好比咱們在項目中只使用了Button,和Table,可是這樣實際上加載了所有的 antd 組件的樣式(對前端性能是個隱患);
所以咱們須要使用按需加載,只加載咱們使用過得組件樣式。

注意:若是是運行了eject ,webpack配置了babelrc: false ,單獨根目錄新建.babelrc會報錯的,須要在webpack.dev.js配置,在module模塊 ,loader: require.resolve('babel-loader')對象中的plugins數組中添加

這裏只展現容許eject暴露了webpack配置文件的配置方式,未暴露webpack配置方式請參考https://segmentfault.com/a/11...

  1. 安裝babel-plugin-import

    npm install --save-dev babel-plugin-import

  2. 給 webpack 的 babel-loader plugins 加上 babel-plugin-import

須要修改兩個文件 /config/webpack.config.prod.js 和 /config/webpack.config.dev.js (修改的內容同樣,升級後的create-react-app合併爲一個文件 webpack.config.js)找到加載 babel-loader 的地方,往他的 plugins 加入以下代碼

[
    require.resolve('babel-plugin-import'),// 導入 import 插件
    {
      libraryName: 'antd',   //暴露antd
      style: 'css'
    }
  ]

最後造成的配置以下(create-react-app 版本不一樣最後的配置可能不同,原理同樣):

// Process application JS with Babel.
    // The preset includes JSX, Flow, TypeScript, and some ESnext features.
    {
      test: /\.(js|mjs|jsx|ts|tsx)$/,
      include: paths.appSrc,
      loader: require.resolve('babel-loader'),
      options: {
        customize: require.resolve(
          'babel-preset-react-app/webpack-overrides'
        ),
        
        plugins: [
          [
            require.resolve('babel-plugin-named-asset-import'),
            {
              loaderMap: {
                svg: {
                  ReactComponent: '@svgr/webpack?-svgo,+ref![path]',
                },
              },
            },
          ],
          // antd按需加載
          [
            require.resolve('babel-plugin-import'),// 導入 import 插件
            {
              libraryName: 'antd',   //暴露antd
              style: 'css'
            }
          ],
        ],
        // This is a feature of `babel-loader` for webpack (not Babel itself).
        // It enables caching results in ./node_modules/.cache/babel-loader/
        // directory for faster rebuilds.
        cacheDirectory: true,
        cacheCompression: isEnvProduction,
        compact: isEnvProduction,
      },
    },

代碼分隔(react-loadable)

一個動態導入加載組件的高階組件.

未使用前

import Home from'./Home';

使用後

import loadable from '@/utils/loadable'
const Home = loadable(() => import('./Home '));

loadable組件

import React from 'react';
import Loadable from 'react-loadable';

//通用的過場組件
const loadingComponent =()=>{
  return (
    <div></div>
  )
};

//過場組件默認採用通用的,若傳入了loading,則採用傳入的過場組件
export default (loader,loading = loadingComponent)=>{
  return Loadable({
    loader,
    loading
  });
}

參考連接

預渲染配置 (Prerender SPA Plugin)

構建階段生成匹配預渲染路徑的 html 文件(注意:每一個須要預渲染的路由都有一個對應的 html)。構建出來的 html 文件已有部份內容。

若是在項目中同時使用代碼分隔預加載會致使頁面閃屏。緣由是會先加載預加載打包出來的html,渲染靜態頁面,而後會請求代碼分隔後該頁面的js。會致使html的root節點再次掛載。所以不推薦使用預加載的同時使用代碼分隔。

配置方式

1.npm install prerender-spa-plugin

2.找到 /config/webpack.config.prod.js文件

const path = require('path')
const PrerenderSPAPlugin = require('prerender-spa-plugin')

module.exports = {
  plugins: [
    ...
    new PrerenderSPAPlugin({
      // Required - The path to the webpack-outputted app to prerender.
      staticDir: path.join(__dirname, '../build'),
      // Required - Routes to render.
      routes: ['/home', '/convert', '/trim', '/merge', '/watermark', '/remove', '/download'],
    })
  ]
}

3.如需添加路由則在 routes 裏面添加,同時須要後端更改ngnix配置

/ -> home/index.html
/home -> home/index.html
/convert -> convert/index.html
/trim -> trim/index.html
/merge -> merge/index.html
/watermark -> watermark/index.html
/remove -> remove/index.html
/download -> download/index.html

除了上面的路徑,其餘路徑所有指向 index.html

單頁應用多路由預渲染指南 http://www.javashuo.com/article/p-hzbhmhhk-mh.html
使用說明 https://github.com/chrisvfritz/prerender-spa-plugin


源碼

爲方便快速構建項目,本例全部配置的代碼均放在github項目中。
https://github.com/zhaosheng8...

相關文章
相關標籤/搜索