在從零開始React同構開發(一)中咱們已經能實現基本的React配置和編譯了。接下來咱們須要將編譯工做工程化。javascript
代碼在這,建議下載後,對照着看,由於文章不方便把全部的代碼貼上來css
項目目錄結構優化html
stylus
樣式文件的處理和打包vue
extract-text-webpack-plugin
配置java
html-webpack-plugin
配置node
配置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" },
前篇文章咱們只編譯了jsx,咱們還沒引入樣式,假設如今項目的css使用stylus
來編寫。那麼能夠參考如下配置。
咱們須要3個loader:
stylus-loader
autoprefixer-loader
css-loader
vue-style-loader
file-loader
和url-loader
這些loaders你們確定耳熟能詳啦,可能你們會對vue-style-loader
會有疑惑,這裏解釋下:
由於在啓用
sourceMap
的狀況下,style-loader
對background-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
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`
能夠看到css都被提取出來成爲單獨的文件了。
html-webpack-plugin
配置做用:
自動生成HTML
自動在HTML引入js
,css
。
自動添加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, }), ]
執行watch
命令
npm run watch
能夠看到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爲例
先修改babel.rc
文件:
{ "presets": [ "react", "es2015" ], "plugins": [ "transform-regenerator", "transform-decorators-legacy" //添加這個 ] }
在config文件夾添加browser-sync.config.js
在common文件夾添加bs.js
在React組件中引入bs.js
執行watch
命令
`npm run watch`
刷新瀏覽器,看到下圖說明自動刷新服務已經成功開啓
減少路徑的書寫量
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', }),