從零開始搭建React同構應用(二):瀏覽器端工程化

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

項目工程化(瀏覽器端)

從零開始React同構開發(一)中咱們已經能實現基本的React配置和編譯了。接下來咱們須要將編譯工做工程化。javascript

代碼

代碼在這,建議下載後,對照着看,由於文章不方便把全部的代碼貼上來css

主要內容

  1. 項目目錄結構優化html

  2. stylus樣式文件的處理和打包vue

  3. extract-text-webpack-plugin配置java

  4. html-webpack-plugin配置node

  5. 配置browser-sync自動刷新(利用es6的decoratort特性)react

項目目錄結構優化

先看下整理後的目錄結構webpack

src
    ├─config //附加webpack配置文件
    ├─module
    │  ├─common //公共模塊
    │  │  └─stylus
    │  ├─index //首頁模塊
    │  │  ├─component
    │  │  └─stylus
    │  │      └─img
    │  └─TodoDetail //todo詳情模塊
    │      └─stylus
    └─template //HTML模版

module文件夾放置了各個模塊,我把頁面以模塊分類,每一個模塊下第一層的.jsx文件就是頁面的入口文件(common除外)。git

common模塊文件夾放置一些公共組件、公共庫、公共樣式等。es6

template文件夾用於放置html-webpack-plugin用到的頁面模版。

固然我還在探索更好的目錄配置方式,你們若是有想法歡迎@我^_^。

添加npm script

咱們先添加一條watch命令,用於開發環境的編譯。

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

樣式文件處理

css、stylus文件的處理

前篇文章咱們只編譯了jsx,咱們還沒引入樣式,假設如今項目的css使用stylus來編寫。那麼能夠參考如下配置。
咱們須要3個loader:

  1. stylus-loader

  2. autoprefixer-loader

  3. css-loader

  4. vue-style-loader

  5. file-loaderurl-loader

這些loaders你們確定耳熟能詳啦,可能你們會對vue-style-loader會有疑惑,這裏解釋下:

由於在啓用sourceMap的狀況下,style-loaderbackground-image屬性沒有處理好,生成的URL連接開頭爲chrome:// urls,官方庫中已經有人提issue了,。

後來尤雨溪大神fork了官方庫後開發了vue-style-loader,完美的解決了background-image問題,當時發現這個庫的時候真的感動的不行啊。。。

下面看一下樣式文件loader的配置

loaders: [
            {
                test: /\.(png|jpe?g|gif)/,
                loader: 'url?limit=1024&name=img/[name].[ext]'
            }, {
                test: /\.(ttf|eot|svg)$/,
                loader: "url?limit=1024&name=fonts/[name].[ext]"
            },
            {
                test: /\.jsx?$/,
                exclude: /node_modules/,
                loader: "babel"
            },
            {
                test: /\.(styl|css)$/,
                loader: "vue-style!css?sourceMap!autoprefixer!stylus")
            },
        ]

這樣就能夠愉快的在js中引入CSS啦

extract-text-webpack-plugin配置

有時候咱們須要把CSS提取出來,單獨打包成一個文件,這時候須要用到extract-text-webpack-plugin

修改webpack.config.js

const ExtractTextPlugin = require("extract-text-webpack-plugin");

而後修改咱們原有的styl-loader配置

{
    test: /\.(styl|css)$/,
    loader: ExtractTextPlugin.extract(["vue-style"], "css?sourceMap!autoprefixer!stylus")
},

咱們還要在plugin字段配置輸出的CSS文件名稱

plugins:[
    new ExtractTextPlugin('css/[name].css'),
]

執行watch命令

`npm run watch`

clipboard.png

能夠看到css都被提取出來成爲單獨的文件了。

html-webpack-plugin配置

做用:

  • 自動生成HTML

  • 自動在HTML引入jscss

  • 自動添加hash。

咱們在src/config新建html-webpack-plugin.config.js文件,因爲配置HTML編譯。

//html-webpack-plugin.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
module.exports = [
    new HtmlWebpackPlugin({
        filename: 'index.html',
        chunks: ['common', 'index'],
        template: path.resolve(__dirname, '../template/base.html'),
        hash: true,
    }),
]

修改webpack.config.js

clipboard.png

執行watch命令

npm run watch

clipboard.png

能夠看到webpack幫咱們自動生成了html文件。

index.html文件內容以下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0"/>
    <title>React同構開發Demo</title>
    <link href="/css/index.css?d8b82face5e26195ca7e" rel="stylesheet">
</head>
<body>
<div id="wrap"></div>
<script type="text/javascript" src="/js/common.js?d8b82face5e26195ca7e"></script>
<script type="text/javascript" src="/js/index.bundle.js?d8b82face5e26195ca7e"></script>
</body>
</html>

配置browser-sync自動刷新

這裏咱們用到ES7的修飾器特性。目前transform-decorators只有第三方的實現。

以Index.jsx爲例

  1. 先修改babel.rc文件:

    {
      "presets": [
        "react",
        "es2015"
      ],
      "plugins": [
        "transform-regenerator",
        "transform-decorators-legacy" //添加這個
      ]
    }
  2. 在config文件夾添加browser-sync.config.js

  3. 修改webpack.config.js
    clipboard.png

  4. 在common文件夾添加bs.js

  5. 在React組件中引入bs.js
    clipboard.png

執行watch命令

`npm run watch`

刷新瀏覽器,看到下圖說明自動刷新服務已經成功開啓
clipboard.png

webapck小技巧

減少路徑的書寫量

resolve: {
    extensions: ['.jsx', '.js', ''],
    alias: {
        'common': path.join(__dirname, 'module/common')
    }
},

自動引入庫,不用每次都寫import

new webpack.ProvidePlugin({
            React: 'react',
            ReactDOM: 'react-dom',
            fetch: 'isomorphic-fetch',
            promise: 'promise'
        }),

區分生產和開發環境

new webpack.DefinePlugin({
        'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV) || JSON.stringify('development'),
    }),

使用cross-env來跨平臺設置環境變量

"scripts": {
    "watch": "webpack -d -w --progress --colors --bs",
    "test-server": "anywhere -p 18341 -d ./build",
    "dist": "cross-env NODE_ENV='production' webpack -p"
  }

提取公共js、css

new webpack.optimize.CommonsChunkPlugin({
        name: 'common',
        filename: 'js/common.js',
    }),
相關文章
相關標籤/搜索