webpack配置React開發環境(上)

Webpack 是一個前端資源加載/打包工具,咱們部門的一條主要技術棧就是Webpack+React+ES6+node,雖然以前本身作我的項目也接觸好屢次Webpack,可是本身並無研讀總結過Webpack的知識點,讀了wepack-demos,這些demos雖然是基於webpack@1.x的,可是舉例得蠻簡潔明瞭,因此此次就簡單翻譯此文的一些重點。javascript

什麼是Webpack?

Webpack是一個前端資源加載/打包工具,只須要相對簡單的配置就能夠提供前端工程化須要的各類功能,而且若是有須要它還能夠被整合到其餘好比 Grunt / Gulp 的工做流。css

安裝 Webpack:npm install -g webpack。html

Webpack 使用一個名爲 webpack.config.js 的配置文件。前端

// webpack.config.js
module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  }
};

一些你應該知道的命令:java

  • webpack —— 進行一次編譯
  • webpack -p —— 進行一次編譯(壓縮成一行)
  • webpack --watch —— 持續編譯
  • webpack -d  —— 編譯完成後包含一個maps文件
  • wepack --colors —— 使壓縮文件變漂亮(我暫時沒看出來)

在開發應用程序時,能夠在package.json文件中編寫scripts字段,以下所示:node

// package.json
{
  // ...
  "scripts": {
    "dev": "webpack-dev-server --devtool eval --progress --colors",
    "deploy": "NODE_ENV=production webpack -p"
  },
  // ...
}

入口文件

入口文件是一個Webpack將會讀取它並將它編譯成bundle.js的文件react

demo01:單個入口文件:jquery

// webpack.config.js
module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  }
};

demo02:多個入口文件:(它對多頁面app是很是有用的)webpack

// index.html
<html>
  <body>
    <script src="bundle1.js"></script>
    <script src="bundle2.js"></script>
  </body>
</html>

// webpack.config.js
module.exports = {
  entry: {
    bundle1: './main1.js',
    bundle2: './main2.js'
  },
  output: {
    filename: '[name].js'
  }
};

Babel-loader

加載器是預處理器,它轉換您的應用程序的資源文件(更多信息)。例如,Babel-loader能夠將JSX / ES6文件轉換爲JS文件。官方文檔有一個完整的加載器列表git

// webpack.config.js
module: {
    loaders:[
      {
        test: /\.js[x]?$/,
        exclude: /node_modules/,
        loader: 'babel-loader?presets[]=es2015&presets[]=react'
      },
    ]
  }

或者
module: {
  loaders: [
    {
      test: /\.jsx?$/,
      exclude: /node_modules/,
      loader: 'babel',
      query: {
        presets: ['es2015', 'react']
      }
    }
  ]
}

CSS-loader

Webpack容許您在JS文件中引用CSS,而後使用CSS-loader預處理CSS文件。

// main.js
require('./app.css');
// webpack.config.js
module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  },
  module: {
    loaders:[
      { test: /\.css$/, loader: 'style-loader!css-loader' },
    ]
  }
};

注意,你必須使用兩個加載器來轉換CSS文件。首先是CSS-loader讀取CSS文件,另外一個是Style-loader將Style標籤插入HTML頁面。不一樣的裝載器經過感嘆號(!)連接。

啓動服務器後,index.html將具備內部樣式表。(demo04)

Image loader

// main.js
var img1 = document.createElement("img");
img1.src = require("./small.png");
document.body.appendChild(img1);

var img2 = document.createElement("img");
img2.src = require("./big.png");
document.body.appendChild(img2);

// index.html
<html>
  <body>
    <script type="text/javascript" src="bundle.js"></script>
  </body>
</html>

// webpack.config.js
module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  },
  module: {
    loaders:[
      { test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192' }
    ]
  }
};

url-loader轉換圖像文件。若是圖像大小小於8192字節,則將其轉換爲數據URL;不然,它將被轉換爲正常的URL。如你所見,問號(?)用於將參數傳遞到加載器。

啓動服務器後,small.png和big.png將有如下URL。

<img src="data:image/png;base64,iVBOR...uQmCC">
<img src="4853ca667a2b8b8844eb2693ac1b2578.png">

UglifyJS Plugin(減小輸出)

Webpack有一個插件系統來擴展其功能。例如,UglifyJs Plugin將縮小輸出(bundle.js)JS代碼。(demo07)

// webpack.config.js
var webpack = require('webpack');
var uglifyJsPlugin = webpack.optimize.UglifyJsPlugin;
module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  },
  plugins: [
    new uglifyJsPlugin({
      compress: {
        warnings: false
      }
    })
  ]
};

壓縮的效果以下:

// 壓縮前
var longVariableName = 'Hello';
longVariableName += ' World';
document.write('<h1>' + longVariableName + '</h1>');

// 壓縮後
var o="Hello";o+=" World",document.write("<h1>"+o+"</h1>")

自動打開瀏覽器&&自動建立index.html

此演示向您演示如何加載第三方插件。 html-webpack-plugin能夠爲您建立index.html,而且當Webpack加載時,open-browser-webpack-plugin能夠打開一個新的瀏覽器選項卡。

// main.js
document.write('<h1>Hello World</h1>');

// webpack.config.js
var HtmlwebpackPlugin = require('html-webpack-plugin');
var OpenBrowserPlugin = require('open-browser-webpack-plugin');

module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  },
  plugins: [
    new HtmlwebpackPlugin({
      title: 'Webpack-demos',
      filename: 'index.html'
    }),
    new OpenBrowserPlugin({
      url: 'http://localhost:8080'
    })
  ]
};

環境標誌

您能夠僅在具備環境標誌的開發環境中啓用一些代碼(demo09)

// main.js
document.write('<h1>Hello World</h1>');

if (__DEV__) {
  document.write(new Date());
}

// index.html
<html>
<body>
  <script src="bundle.js"></script>
</body>
</html>

// webpack.config.js
var webpack = require('webpack');

var devFlagPlugin = new webpack.DefinePlugin({
  __DEV__: JSON.stringify(JSON.parse(process.env.DEBUG || 'false'))
});

module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  },
  plugins: [devFlagPlugin]
};

而後如今將環境變量傳遞到webpack。

# Linux & Mac
$ env DEBUG=true webpack-dev-server

# Windows
$ set DEBUG=true
$ webpack-dev-server

Common chunk(抽出公用腳本)

當多腳本具備公共塊時,可使用CommonsChunkPlugin將公共部分提取到單獨的文件中。

// main1.jsx
var React = require('react');
var ReactDOM = require('react-dom');

ReactDOM.render(
  <h1>Hello World</h1>,
  document.getElementById('a')
);

// main2.jsx
var React = require('react');
var ReactDOM = require('react-dom');

ReactDOM.render(
  <h2>Hello Webpack</h2>,
  document.getElementById('b')
);

// index.html
<html>
  <body>
    <div id="a"></div>
    <div id="b"></div>
    <script src="init.js"></script>
    <script src="bundle1.js"></script>
    <script src="bundle2.js"></script>
  </body>
</html>

// webpack.config.js
var CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlugin");
module.exports = {
  entry: {
    bundle1: './main1.jsx',
    bundle2: './main2.jsx'
  },
  output: {
    filename: '[name].js'
  },
  module: {
    loaders:[
      {
        test: /\.js[x]?$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        query: {
          presets: ['es2015', 'react']
        }
      },
    ]
  },
  plugins: [
    new CommonsChunkPlugin('init.js')
  ]
}

Vendor chunk

您還可使用CommonsChunkPlugin從腳本中將供應商庫提取到單獨的文件中。(優化代碼層面)

// main.js
var $ = require('jquery');
$('h1').text('Hello World');

// index.html
<html>
  <body>
    <h1></h1>
    <script src="vendor.js"></script>
    <script src="bundle.js"></script>
  </body>
</html>

// webpack.config.js
var webpack = require('webpack');

module.exports = {
  entry: {
    app: './main.js',
    vendor: ['jquery'],
  },
  output: {
    filename: 'bundle.js'
  },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin(/* chunkName= */'vendor', /* filename= */'vendor.js')
  ]
};

若是你想要一個模塊做爲變量在每一個模塊,如使$和jQuery可用在每一個模塊沒有寫require(「jquery」)。你應該使用ProvidePlugin(官方文檔)。

// main.js
$('h1').text('Hello World');


// webpack.config.js
var webpack = require('webpack');

module.exports = {
  entry: {
    app: './main.js'
  },
  output: {
    filename: 'bundle.js'
  },
  plugins: [
    new webpack.ProvidePlugin({
      $: "jquery",
      jQuery: "jquery",
      "window.jQuery": "jquery"
    })
  ]
};

熱更新

熱模塊替換(HMR)交換,添加或刪除模塊,而應用程序正在運行,而沒有頁面從新加載。

您有兩種方法經過webpack-dev-server啓用熱模塊更換。

(1)在命令行中指定--hot和--inline

$ webpack-dev-server --hot --inline

選項的含義:

  • --hot: 添加HotModuleReplacementPlugin並將服務器切換到熱模式。
  • --inline: 將webpack-dev-server運行時嵌入到bundle中。
  • --hot --inline: 還添加了webpack/hot/dev-server條目。

(2)修改webpack.config.js文件(demo15)

  • 添加新webpack.HotModuleReplacementPlugin() 的插件
  • 添加webpack/hot/dev-server 和 webpack-dev-server/client?http://localhost:8080 到輸入字段
// webpack.config.js
var webpack = require('webpack');
var path = require('path');

module.exports = {
  entry: [
    'webpack/hot/dev-server',
    'webpack-dev-server/client?http://localhost:8080',
    './index.js'
  ],
  output: {
    filename: 'bundle.js',
    publicPath: '/static/'
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin()
  ],
  module: {
    loaders: [{
      test: /\.jsx?$/,
      exclude: /node_modules/,
      loader: 'babel-loader',
      query: {
        presets: ['es2015', 'react']
      },
      include: path.join(__dirname, '.')
    }]
  }
};
// App.js
import React, { Component } from 'react';

export default class App extends Component {
  render() {
    return (
      <h1>Hello World</h1>
    );
  }
}

// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(<App />, document.getElementById('root'));

// index.html
<html>
  <body>
    <div id='root'></div>
    <script src="/static/bundle.js"></script>
  </body>
</html>

有用的連接

 下回會學習總結webpack2的配置相關總結,有不錯的文章歡迎分享。

相關文章
相關標籤/搜索