原文:https://segmentfault.com/a/1190000016342792
寫在前面
每次構建react項目的時候都會配置一大堆東西,時間久了就會忘記怎么配置。為了方便自己記憶也為了其他開發者在構建react應用時能夠快速開發,故作此記錄。
本項目基於create-react-app
腳手架進行配置。主要配置了一些項目開發中常用的方法,比如 webpack的sass
,redux
、熱加載
、代理
以及其他工具庫的引入等等。
初始化項目
首先,要先利用create-react-app創建一個react項目,可參考 https://github.com/facebookin...
安裝 create-react-app
npm install -g create-react-app
創建一個應用程序
create-react-app my-app cd my-app
注:my-app是指項目的名稱,用戶可以自定義項目名稱
這個時候可以在命令行輸入
npm start
: 啟動項目就能看到項目啟動頁面了。
npm run build
: 項目發布。
這樣一個簡單的react項目就初始化完畢了。
但是,默認所有配置是隱藏起來的,要想自定義配置,需要運行一個命令:npm run eject
此時會提示,該命令不可逆,是否繼續,輸入y,這樣所有配置項就都出來了。會生成一個config
文件夾,這時候也可以做一些定制化的配置了。
項目配置
兼容IE
引入element-react
UI框架會報錯 ReferenceError: “Symbol”未定義
- 解決方案:
項目中引入babel-polyfill
,在app.js中導入即可
配置webpack
基於webpack的一些配置
配置sass
腳手架默認沒有配置sass,項目中如果使用sass需要單獨配置
1、安裝依賴 npm install --save-d node-sass sass-loader
2、修改config下面的webpack.config.dev.js
和webpack.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版本使用方式不同
配置redux
配置 @connect
裝飾器
在項目中可以直接通過@connect方式訪問redux
未配置
配置后
需要說明的是,這里用了裝飾器,需要安裝模塊babel-plugin-transform-decorators-legacy
然后在package.json里面配置plugins
項目中其他工具配置
classnames
在react 中切換className比較麻煩,簡單的可以使用三目運算,但是復雜一點的class就比較麻煩了,比如這個稍微復雜點的div動態切換多個className, 推薦一個工具庫,可以簡單方便的切換className.
<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...
- 安裝babel-plugin-import
npm install --save-dev babel-plugin-import
- 給 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
單頁應用多路由預渲染指南 https://juejin.im/post/59d49d976fb9a00a571d651d
使用說明 https://github.com/chrisvfritz/prerender-spa-plugin
源碼
為方便快速構建項目,本例所有配置的代碼均放在github項目中。
https://github.com/zhaosheng8...