從零開始搭建React同構應用(一)

從零開始搭建React同構應用(一)

前言

畢業入職公司後開始搞React,從剛開始只會簡單的setState,到後面webpack複雜的配置,Redux,Server Render,都一一上手。期間遇到不少問題,踩過不少坑,最近想以blog的方式把本身開發React同構應用的歷程記錄下來,一方面能夠和你們分享下使用React的經驗,另外一方面也算是對本身一年來工做的小總結。javascript

主要內容

  • webpack配置java

  • babel-loader的配置node

  • 在瀏覽器環境中使用async函數react

代碼

這邊文章的Demo我已經上傳至Githubwebpack

安裝webpack

npm install webpack -Dgit

這裏要說明的一點是,webpack通常是全局安裝,不過接下來的項目採用npm命令來編譯配置,npm run command執行時會自動添加node_modules/.bin目錄至PATH環境變量,所以不用擔憂找不到命令。es6

配置webpack.config.js

先建立一個最簡單的webpack配置文件。github

const path = require('path');
//入口文件
let entry = {
    index: './module/index/Index_entry.js'
};

//瀏覽器端的配置
let browserConfig = {
    entry,
    output: {
        path: path.join(__dirname, 'build'),
        publicPath: '/build',
        filename: "js/[name].bundle.js",
        chunkFilename: "js/[id].bundle.js"
    },
    module: {
        loaders: [
            {
                test: /\.jsx?$/,
                exclude: /node_modules/,
                loader: `babel`,
            }
        ]
    }
};

module.exports = [browserConfig];

這裏我將entrybrowserConfig獨立開來,module.exports導出的是一個數組,這是爲了方便後面server render的配置。web

更詳細的配置說明,能夠參照webapck的官方文檔,這裏就不一一說明了。npm

babel的配置

babel能作什麼

通常我在開發React app的工做中有三個需求

  • 將JSX轉換成ES5語法

  • 將ES7轉換成ES5語法

  • 啓用async函數的支持

安裝babel-loader

先安裝babel-corebabel-loader

npm install --save-dev babel-loader babel-core

在我剛剛學習webpack的時候,天真的覺得裝完這兩個包,就能夠轉碼JSX了,結果就是一直報錯,提示說不識別JSX語法。。。弄的我疑惑了好久。。。後來才知道,裝完上面兩個包以後,還須要進一步的配置(presets),好比指定babel將當前的es7的代碼轉換到 es2015 的代碼,將JSX語法 <Component/> 轉換成React.createElement(Component)等等。

配置.babelrc

babel官方預先設定了6個經常使用的presets,咱們日常須要的是babel-preset-es2015babel-preset-react

npm install --save-dev babel-preset-es2015 babel-preset-react

在項目根目錄建立.babelrc。固然這裏也能夠在webpack.config.js中的loaders配置。不過我的以爲在.babelrc中配置會更清晰一些。

{
  "presets": [
    "react",
    "es2015"
  ]
}

這樣前兩個需求就能夠完美解決了,哈哈。

啓用async函數

regenerator函數讓咱們有把異步的函數寫成同步的能力,使得代碼的可維護性和可閱讀性大大提升,而async則是regenerator的語法糖,通常來講regenerator函數的執行是須要co做爲其執行器的,而async函數不用,所以使用起來更加方便優雅。關於async函數的知識能夠參考阮一峯大神的書籍ECMAScript 6 入門

若是如今用上面的配置,直接使用regenerator函數的話,會報regeneratorRuntime is not defined錯誤,這個錯誤以前也是困擾過我,後面才知道,regenerator沒法直接被編譯成es5的代碼。必須添加polyfill,即regeneratorruntime庫才能運行。

先安裝對應的babel plugin,這個插件默認會幫咱們把async函數轉換成regenerator函數。

npm install babel-plugin-transform-regenerator

代碼轉換好了後,代碼運行時還要一個包 regenerator-runtime/runtime

npm i regenerator-runtime -S

而後在用到async函數的文件頭部添加

import 'regenerator-runtime/runtime';

好比在Index.jsx

import React from 'react';
import 'regenerator-runtime/runtime';

export default class extends React.Component {
    constructor() {
        super();

        this.state = {
            pageData: 'loading'
        }
    }

    getAsyncData() {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve({
                    code: 200,
                    msg: 'success',
                    data: 'hello!'
                })
            }, 2000)
        });
    }

    async componentDidMount() {

        let data = await this.getAsyncData();

        this.setState({
            pageData: data.data
        })

    }

    render() {
        return (
            <div>
                data: {this.state.pageData}
            </div>
        )
    }

}

.babelrc修改爲以下所示

{
  "presets": [
    "react",
    "es2015"
  ],
  "plugins": [
    "transform-regenerator"
  ]
}

至此,babel能夠完美解決咱們上面提出的3個需求啦。讓咱們能夠先編譯試試。
如今package.json中添加

"scripts": {
    "watch": "webpack -d -w --progress --colors"
  },

執行npm run watch

ok,編譯成功

搭建一個簡單的靜態文件服務器

推薦使用anywhere,詳細配置在這

npm i anywhere -g

添加npm script

"scripts": {
    "watch": "webpack -d -w --progress --colors",
    "test-server": "anywhere -s -p 8000 -d ./build"
  },

咱們啓動HTTP服務器

npm run test-server

打開http://127.0.0.1:8000/,正常的話以下圖所示

你們想親自嘗試的能夠fork一份代碼研究,哈哈。

第一次寫文章,你們多多包涵,有什麼錯誤儘管指出來,^_^。

相關文章
相關標籤/搜索