webpack1 新手入門教程

本文github倉庫地址: https://github.com/Rynxiao/webpack-tutorial ,裏面包括了本教程的全部代碼。javascript

【若是你以爲這篇文章寫得不錯,麻煩給本倉庫一顆星:-D】css

1. 導語

1.1 什麼叫作webpack

webpack is a module bundler.
webpack takes modules with dependencies and generates static assets representing those modules.html

簡單的歸納就是:webpack是一個模塊打包工具,處理模塊之間的依賴同時生成對應模塊的靜態資源。前端

1.2 webpack能夠作一些什麼事情

這裏寫圖片描述

圖中已經很清楚的反應了幾個信息:java

  • webpack把項目中全部的靜態文件都看做一個模塊
  • 模快之間存在着一些列的依賴
  • 多頁面的靜態資源生成(打包以後生成多個靜態文件,涉及到代碼拆分)

2. webpack安裝

  • 全局安裝(供全局調用:如webpack --config webpack.config.js)
npm install -g webpack
  • 項目安裝
npm install webpack

// 處理相似以下調用
import webpack from "webpack";
var webpack = require("webpack");

建議安裝淘寶的npm鏡像,這樣下載npm包會快上不少,具體作法:node

// 方式一
npm install xx --registry=https://registry.npm.taobao.org/

// 方式二:安裝淘寶提供的npm工具
npm install -g cnpm
cnpm install xx

// 方式三
// 在用戶主目錄下,找到.npmrc文件,加上下面這段配置
registry=https://registry.npm.taobao.org/

3. webpack的基本配置

建立配置文件(webpack.config.js,執行webpack命令的時候,默認會執行這個文件)react

module.export = {
    entry : 'app.js',
    output : {
        path : 'assets/',
        filename : '[name].bundle.js'
    },
    module : {
        loaders : [
            // 使用babel-loader解析js或者jsx模塊
            { test : /\.js|\.jsx$/, loader : 'babel' },
            // 使用css-loader解析css模塊
            { test : /\.css$/, loader : 'style!css' },
            // or another way
            { test : /\.css$/, loader : ['style', 'css'] }
        ]
    }
};

說明一: webpack.config.js默認輸出一個webpack的配置文件,與CLI方式調用相同,只是更加簡便
說明二: 執行webpack命令便可以運行配置,先決條件,全局安裝webpack,項目安裝各模塊loader
說明三: entry對應須要打包的入口js文件,output對應輸出的目錄以及文件名,module中的loaders對應解析各個模塊時須要的加載器jquery

一個簡單的例子webpack

basic/app.jsgit

require('./app.css');
document.getElementById('container').textContent = 'APP';

basic/app.css

* {
    margin: 0;
    padding: 0;
}
#container {
    margin: 50px auto;
    width: 50%;
    height: 200px;
    line-height: 200px;
    border-radius: 5px;
    box-shadow: 0 0 .5em #000;
    text-align: center;
    font-size: 40px;
    font-weight: bold;
}

basic/webpack.config.js

/**
 * webpack打包配置文件
 */

module.exports = {
    // 若是你有多個入口js,須要打包在一個文件中,那麼你能夠這麼寫 
    // entry : ['./app1.js', './app2.js']
    entry : './app.js',
    output : {
        path : './assets/',
        filename : '[name].bundle.js'
    },
    module : {
        loaders : [
            { test : /\.js$/, loader : 'babel' },
            { test : /\.css$/, loader : 'style!css' }
        ]
    }
};

basic/index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>basic webpack</title>
</head>
<body>
    <div id="container"></div>
    <script src="./assets/main.bundle.js"></script>
</body>
</html>

basic文件夾執行webpack,打包信息以下

這裏寫圖片描述

生成main.bundle.js文件,chunk名稱爲main,也是webpack默認生成的chunk

## 4. webapck經常使用到的各點拆分

### 4.1 entry相關

4.1.1webpack的多入口配置

上例的簡單配置中,只有一個入口文件,那麼若是對應於一個頁面須要加載多個打包文件或者多個頁面想同時引入對應的打包文件的時候,應該怎麼作?

entry : {
    app1 : './app1.js',
    app2 : './app2.js'
}

multi-entry文件夾執行webpack,打包信息以下

這裏寫圖片描述

可見生成了兩個入口文件,以及各自對應的chunk


### 4.2 output相關

4.2.1 output.publicPath

output: {
    path: "/home/proj/cdn/assets/[hash]",
    publicPath: "http://cdn.example.com/assets/[hash]/"
}

引用一段官網的話:

The publicPath specifies the public URL address of the output files when referenced in a browser. For loaders that embed <script> or <link> tags or reference assets like images, publicPath is used as the href or url() to the file when it’s different then their location on disk (as specified by path).

大體意思就是:publicPath指定了你在瀏覽器中用什麼地址來引用你的靜態文件,它會包括你的圖片、腳本以及樣式加載的地址,通常用於線上發佈以及CDN部署的時候使用。

好比有下面一段配置:

var path = require('path');
var HtmlWebpackPlugin =  require('html-webpack-plugin');

module.exports = {
    entry : './app.js',
    output : {
        path : './assets/',
        filename : '[name].bundle.js',
        publicPath : 'http://rynxiao.com/assets/'
    },
    module : {
        loaders : [
            { test : /\.js$/, loader : 'babel' },
            { test : /\.css$/, loader : 'style!css' }
        ]
    },
    plugins : [
        new HtmlWebpackPlugin({
            filename: './index-release.html',
            template: path.resolve('index.template'),
            inject: 'body'
        })
    ]
};

其中我將publicPath設置成了http://rynxiao.com/assets/,其中設置到了插件的一些東西,這點下面會講到,總之這個插件的做用是生成了上線發佈時候的首頁文件,其中script中引用的路徑將會被替換。以下圖:

這裏寫圖片描述


4.2.2 output.chunkFilename

各個文件除了主模塊之外,還可能生成許多額外附加的塊,好比在模塊中採用代碼分割就會出現這樣的狀況。其中chunkFilename中包含如下的文件生成規則:

[id] 會被對應塊的id替換.

[name] 會被對應塊的name替換(或者被id替換,若是這個塊沒有name).

[hash] 會被文件hash替換.

[chunkhash] 會被塊文件hash替換.

例如,我在output中以下設置:

output : {
    path : './assets/',
    filename : '[name].[hash].bundle.js',
    chunkFilename: "chunk/[chunkhash].chunk.js"
}

同時我修改了一下basic/app.js中的文件

require('./app.css');

require.ensure('./main.js', function(require) {
    require('./chunk.js');
});

document.getElementById("container").textContent = "APP";

其中對應的chunk.js就會生成帶有chunkhashchunk文件,以下圖:

這裏寫圖片描述

這在作給文件打版本號的時候特別有用,當時如何進行hash替換,下面會講到


4.2.3 output.library

這個配置做爲庫發佈的時候會用到,配置的名字即爲庫的名字,一般能夠搭配libraryTarget進行使用。例如我給basic/webpack.config.js加上這樣的配置:

output : {
    // ...
    library : 'testLibrary'
    // ...
}

那麼實際上生成出來的main.bundle.js中會默認帶上如下代碼:

var testLibrary = (//....之前的打包生成的代碼);
// 這樣在直接引入這個庫的時候,就能夠直接使用`testLibrary`這個變量

這裏寫圖片描述


4.2.4 output.libraryTarget

規定了以哪種方式輸出你的庫,好比:amd/cmd/或者直接變量,具體包括以下

"var" - 以直接變量輸出(默認library方式) var Library = xxx (default)

"this" - 經過設置this的屬性輸出 this["Library"] = xxx

"commonjs" - 經過設置exports的屬性輸出 exports["Library"] = xxx

"commonjs2" - 經過設置module.exports的屬性輸出 module.exports = xxx

"amd" - 以amd方式輸出

"umd" - 結合commonjs2/amd/root

例如我以umd方式輸出,如圖:

這裏寫圖片描述


### 4.3 module相關

4.3.1 loader!表明的含義

require("!style!css!less!bootstrap/less/bootstrap.less");
// => the file "bootstrap.less" in the folder "less" in the "bootstrap"
// module (that is installed from github to "node_modules") is
// transformed by the "less-loader". The result is transformed by the
// "css-loader" and then by the "style-loader".
// If configuration has some transforms bound to the file, they will not be applied.

表明加載器的流式調用,例如:

{ test : /\.css|\.less$/, loader : 'style!css!less' }

就表明了先使用less加載器來解釋less文件,而後使用css加載器來解析less解析後的文件,依次類推


4.3.2 loaders中的includeexclude

include表示必需要包含的文件或者目錄,而exclude的表示須要排除的目錄

好比咱們在配置中通常要排除node_modules目錄,就能夠這樣寫

{ 
    test : /\.js$/, 
    loader : 'babel',
    exclude : nodeModuleDir 
}

官方建議:優先採用include,而且include最好是文件目錄


4.3.3 module.noParse

使用了noParse的模塊將不會被loaders解析,因此當咱們使用的庫若是太大,而且其中不包含requiredefine或者相似的關鍵字的時候(由於這些模塊加載並不會被解析,因此就會報錯),咱們就可使用這項配置來提高性能。

例以下面的例子:在basic/目錄中新增no-parse.js

var cheerio = require('cheerio');

module.exports = function() {
    console.log(cheerio);
}

webpack.config.js中新增以下配置:

module : {
    loaders : [
        { test : /\.js$/, loader : 'babel' },
        { test : /\.css$/, loader : 'style!css' }
    ],
    noParse : /no-parse.js/
}

當執行打包後,在瀏覽器中打開index.html時,就會報錯require is not defined

這裏寫圖片描述

4.4 resolve相關

4.4.1 resolve.alias

爲模塊設置別名,可以讓開發者指定一些模塊的引用路徑。對一些常常要被import或者require的庫,如react,咱們最好能夠直接指定它們的位置,這樣webpack能夠省下很多搜索硬盤的時間。
例如咱們修改basic/app.js中的相關內容:

var moment = require("moment");

document.getElementById("container").textContent = moment().locale('zh-cn').format('LLLL');

加載一個操做時間的類庫,讓它顯示當前的時間。使用webpack --profile --colors --display-modules執行配置文件,獲得以下結果:

這裏寫圖片描述

其中會發現,打包總共生成了104個隱藏文件,其中一半的時間都在處理關於moment類庫相關的事情,好比尋找moment依賴的一些類庫等等。

basic/webpack.config.js加入以下配置,而後執行配置文件

resolve : {
    alias : {
        moment : 'moment/min/moment-with-locales.min.js'
    }
}

這裏寫圖片描述

有沒有發現打包的時間已經被大大縮短,而且也只產生了兩個隱藏文件。

配合module.noParse使用

module.noParse參看上面的解釋

noParse: [/moment-with-locales/]

執行打包後,效果以下:

這裏寫圖片描述

是否是發現打包的時間進一步縮短了。

配合externals使用

externals參看下面的解釋

Webpack 是如此的強大,用其打包的腳本能夠運行在多種環境下,Web 環境只是其默認的一種,也是最經常使用的一種。考慮到 Web 上有不少的公用 CDN 服務,那麼 怎麼將 Webpack 和公用的 CDN 結合使用呢?方法是使用 externals 聲明一個外部依賴。

externals: {
    moment: true
}

固然了 HTML 代碼裏須要加上一行

<script src="//apps.bdimg.com/libs/moment/2.8.3/moment-with-locales.min.js"></script>

執行打包後,效果以下:

這裏寫圖片描述


4.4.2 resolve.extensions

resolve : {
    extensions: ["", ".webpack.js", ".web.js", ".js", ".less"]
}

這項配置的做用是自動加上文件的擴展名,好比你有以下代碼:

require('style.less');

var app = require('./app.js');

那麼加上這項配置以後,你能夠寫成:

require('style');

var app = require('./app');

4.5 externals

當咱們想在項目中require一些其餘的類庫或者API,而又不想讓這些類庫的源碼被構建到運行時文件中,這在實際開發中頗有必要。此時咱們就能夠經過配置externals參數來解決這個問題:

//webpack.config.js
module.exports = {
    externals: {
      'react': 'React'
    },
    //...
}

externals對象的key是給require時用的,好比require('react'),對象的value表示的是如何在global(即window)中訪問到該對象,這裏是window.React。

同理jquery的話就能夠這樣寫:'jquery': 'jQuery',那麼require('jquery')便可。

HTML中注意引入順序便可:

<script src="react.min.js" />
<script src="bundle.js" />

4.6 devtool

提供了一些方式來使得代碼調試更加方便,由於打包以後的代碼是合併之後的代碼,不利於排錯和定位。其中有以下幾種方式,參見官網devtool

例如,我在basic/app.js中增長以下配置:

require('./app.css');

// 新增hello.js,顯然在文件夾中是不會存在hello.js文件的,這裏會報錯
require('./hello.js');

document.getElementById("container").textContent = "APP";

執行文件,以後運行index.html,報錯結果以下:

這裏寫圖片描述

給出的提示實在main.bundle.js第48行,點進去看其中的報錯以下:

這裏寫圖片描述

從這裏你徹底看不出到底你程序的哪一個地方出錯了,而且這裏的行數還算少,當一個文件出現了上千行的時候,你定位bug的時間將會更長。

增長devtool文件配置,以下:

module.exports = {
    devtool: 'eval-source-map',
    // ....
};

執行文件,以後運行index.html,報錯結果以下:

這裏寫圖片描述

這裏發現直接定位到了app.js,而且報出了在第二行出錯,點擊去看其中的報錯以下:

這裏寫圖片描述

發現問題定位一目瞭然。

5. webpack經常使用技巧

### 5.1 代碼塊劃分

5.1.1 Commonjs採用require.ensure來產生chunk

require.ensure(dependencies, callback);

//static imports
import _ from 'lodash'

// dynamic imports
require.ensure([], function(require) {
  let contacts = require('./contacts')
})

這一點在output.chunkFileName中已經作過演示,能夠去查看


5.1.2 AMD採用require來產生chunk

require(["module-a", "module-b"], function(a, b) {
    // ...
});

5.1.3 將項目APP代碼與公共庫文件單獨打包

咱們在basic/app.js中添加以下代碼

var $ = require('juqery'),
    _ = require('underscore');

//.....

而後咱們在配置文件中添加vendor,以及運用代碼分離的插件對生成的vendor塊從新命名

var webpack = require("webpack");

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

運行配置文件,效果以下:

這裏寫圖片描述


5.1.4 抽取多入口文件的公共部分

咱們從新創建一個文件夾叫作common,有以下文件:

// common/app1.js

console.log("APP1");
// common/app2.js

console.log("APP2");

打包以後生成的app1.bundle.jsapp2.bundle.js中會存在許多公共代碼,咱們能夠將它提取出來。

// common/webpack.config.js

/**
 * webpack打包配置文件
 * 抽取公共部分js
 */

var webpack = require('webpack');

module.exports = {
    entry : {
        app1 : './app1.js',
        app2 : './app2.js'
    },
    output : {
        path : './assets/',
        filename : '[name].bundle.js'
    },
    module : {
        loaders : [
            { test : /\.js$/, loader : 'babel' },
            { test : /\.css$/, loader : 'style!css' }
        ]
    },
    plugins : [
        new webpack.optimize.CommonsChunkPlugin("common.js")
    ]
};

抽取出的公共js爲common.js,如圖

這裏寫圖片描述

查看app1.bundle.js,發現打包的內容基本是咱們在模塊中所寫的代碼,公共部分已經被提出到common.js中去了

這裏寫圖片描述

5.1.5 抽取css文件,打包成css bundle

默認狀況下以require('style.css')狀況下導入樣式文件,會直接在index.html<head>中生成<style>標籤,屬於內聯。若是咱們想將這些css文件提取出來,能夠按照下面的配置去作。

// extract-css/app1.js
require('./app1.css');
document.getElementById("container").textContent = "APP";

// extract-css/app2.js
require('./app2.css');
document.getElementById("container").textContent = "APP1 APP2";

// extract-css/app1.css
* {
    margin: 0;
    padding: 0;
}
#container {
    margin: 50px auto;
    width: 50%;
    height: 200px;
    line-height: 200px;
    border-radius: 5px;
    box-shadow: 0 0 .5em #000;
    text-align: center;
    font-size: 40px;
    font-weight: bold;
}

// extract-css/app2.css
#container {
    background-color: #f0f0f0;
}

// extract-css/webpack.config.js
/**
 * webpack打包配置文件
 * 抽取公共樣式(沒有chunk)
 */

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

module.exports = {
    entry : {
        app1 : './app1.js',
        app2 : './app1.js'
    },
    output : {
        path : './assets/',
        filename : '[name].bundle.js'
    },
    module : {
        loaders : [
            { test : /\.js$/, loader : 'babel' },
            { test : /\.css$/, loader : ExtractTextPlugin.extract("style-loader", "css-loader") }
        ]
    },
    plugins : [
        new ExtractTextPlugin("[name].css")
    ]
};

獲得的效果以下圖:

這裏寫圖片描述

若是包含chunk文件,而且chunk文件中也由於了樣式文件,那麼樣式文件會嵌入到js中

css合併到一個文件

// ...
module.exports = {
    // ...
    plugins: [
        new ExtractTextPlugin("style.css", {
            allChunks: true
        })
    ]
}

效果如圖:

這裏寫圖片描述

若是包含chunk文件,而且chunk文件中也由於了樣式文件,樣式文件不會嵌入到js中,而是直接輸出到style.css

配合CommonsChunkPlugin一塊兒使用

// ...
module.exports = {
    // ...
    plugins: [
        new webpack.optimize.CommonsChunkPlugin("commons", "commons.js"),
        new ExtractTextPlugin("[name].css")
    ]
}

效果圖以下:

這裏寫圖片描述


5.2 如何給文件打版本

線上發佈時爲了防止瀏覽器緩存靜態資源而改變文件版本,這裏提供兩種作法:

5.2.1 使用HtmlWebpackPlugin插件

// version/webpack.config.js

/**
 * webpack打包配置文件
 * 文件打版本,線上發佈
 */

var path = require('path');
var HtmlWebpackPlugin =  require('html-webpack-plugin');

module.exports = {
    entry : './app.js',
    output : {
        path : './assets/',
        filename : '[name].[hash].bundle.js',
        publicPath : 'http://rynxiao.com/assets/'
    },
    module : {
        loaders : [
            { test : /\.js$/, loader : 'babel' },
            { test : /\.css$/, loader : 'style!css' }
        ]
    },
    plugins : [
        new HtmlWebpackPlugin({
            filename: './index-release.html',
            template: path.resolve('index.template'),
            inject: 'body'
        })
    ]
};

生成的效果以下:

這裏寫圖片描述

每次打包以後都會生成文件hash,這樣就作到了版本控制


5.2.2 自定義插件給文件添加版本

// version/webpack.config.version.js

/**
 * webpack打包配置文件
 * 文件打版本,線上發佈,自定義插件方式
 */

var path = require('path');
var fs = require('fs');
var cheerio = require('cheerio');

module.exports = {
    entry : './app.js',
    output : {
        path : './assets/',
        filename : '[name].[hash].bundle.js',
        publicPath : 'http://rynxiao.com/assets/'
    },
    module : {
        loaders : [
            { test : /\.js$/, loader : 'babel' },
            { test : /\.css$/, loader : 'style!css' }
        ]
    },
    plugins : [
        function() {
            this.plugin("done", function(stats) {
                fs.writeFileSync(
                    path.join(__dirname, "stats.json"),
                    JSON.stringify(stats.toJson())
                );
                fs.readFile('./index.html', function(err, data) {
                    var $ = cheerio.load(data.toString());
                   $('script[src*=assets]').attr('src','http://rynxiao.com/assets/main.' 
                            + stats.hash +'.bundle.js');
                    fs.writeFile('./index.html', $.html(), function(err) {
                        !err && console.log('Set has success: '+ stats.hash)
                    })
                })
            });
        }
    ]
};

效果如圖:

這裏寫圖片描述

能夠達到一樣的效果,可是stats暫時只能拿到hash值,由於咱們只能考慮在hash上作版本控制,好比咱們能夠建hash目錄等等


5.3 shim

好比有以下場景:咱們用到 Pen 這個模塊, 這個模塊對依賴一個 window.jQuery, 可我手頭的 jQuery 是 CommonJS 語法的,而 Pen 對象又是生成好了綁在全局的, 但是我又須要經過 require('pen') 獲取變量。 最終的寫法就是作 Shim 處理直接提供支持:

作法一:

{test: require.resolve('jquery'), loader: 'expose?jQuery'}, // 輸出jQuery到全局
{test: require.resolve('pen'), loader: 'exports?window.Pen'}    // 將Pen做爲一個模塊引入

作法二:

new webpack.ProvidePlugin({
    $: "jquery",
    jQuery: "jquery",
    "window.jQuery": "jquery"
})

This plugin makes a module available as variable in every module.
The module is required only if you use the variable.
Example: Make $ and jQuery available in every module without writing require("jquery").


5.4 怎樣寫一個loader

Loader 是支持鏈式執行的,如處理 sass 文件的 loader,能夠由 sass-loader、css-loader、style-loader 組成,由 compiler 對其由右向左執行,第一個 Loader 將會拿到需處理的原內容,上一個 Loader 處理後的結果回傳給下一個接着處理,最後的 Loader 將處理後的結果以 String 或 Buffer 的形式返回給 compiler。當然也是但願每一個 loader 只作該作的事,純粹的事,而不但願一籮筐的功能都集成到一個 Loader 中。

官網給出了兩種寫法:

// Identity loader
module.exports = function(source) {
  return source;
};
// Identity loader with SourceMap support
module.exports = function(source, map) {
  this.callback(null, source, map);
};

第一種爲基礎的寫法,採用return返回, 是由於是同步類的 Loader 且返回的內容惟一。若是你寫loader有依賴的話,一樣的你也能夠在頭部進行引用,好比:

// Module dependencies.
var fs = require("fs");
module.exports = function(source) {
  return source;
};

而第二種則是但願多個loader之間鏈式調用,將上一個loader返回的結果傳遞給下一個loader

案例

好比我想開發一個es6-loader,專門用來作以.es6文件名結尾的文件處理,那麼咱們能夠這麼寫

// loader/es6-loader.js
// 固然若是我這裏不想將這個loader所返回的東西傳遞給下一個laoder,那麼我
// 能夠在最後直接返回return source
// 這裏改變以後,我直接能夠扔給babel-loader進行處理
module.exports = function(source, map) {
    // 接收es6結尾文件,進行source改變
    source = "console.log('I changed in loader');"
    // 打印傳遞進來的參數
    console.log("param", this.query);
    // ... 咱們還能夠作一些其餘的邏輯處理
    this.callback(null, source, map);
};

// loader/loader1.es6
let a = 1;
console.log(a);

// loader/app.js
// 向loader中傳遞參數
require('./es6-loader?param1=p1!./loader1.es6');
document.getElementById("container").textContent = "APP";

執行webpack打包命令,在控制檯會打印出param的值,如圖:

這裏寫圖片描述

在執行完成以後,打開index.html,在控制檯打印出「I changed in loader」,而不是1

這裏寫圖片描述

進階

能夠去閱讀如下這篇文章 如何開發一個 Webpack loader


5.4 怎樣寫一個plugin

插件基本的結構

插件是能夠實例化的對象,在它的prototype上必須綁定一個apply方法。這個方法會在插件安裝的時候被Webpack compiler進行調用。

function HelloWorldPlugin(options) {
    // Setup the plugin instance with options...
}

HelloWorldPlugin.prototype.apply = function(compiler) {
    compiler.plugin('done', function() {
        console.log('Hello World!'); 
    });
};

module.exports = HelloWorldPlugin;

安裝一個插件,將其添加到配置中的plugins數組中。

var HelloWorldPlugin = require('hello-world');

var webpackConfig = {
// ... config settings here ...
    plugins: [
        new HelloWorldPlugin({options: true})
    ]
};

執行效果如圖:

這裏寫圖片描述

這裏只做簡單的引入,日常通常都不須要本身寫插件,若是想進一步瞭解,能夠去看官網例子

5.5 佈置一個本地服務器

// 1.全局安裝webpack-dev-server
cnpm install -g webpack-dev-server

// 2. 設置一個文件啓動目錄,運行
webpack-dev-server --content-base basic/

// 3. 在瀏覽器輸入localhost:8080

5.6 熱替換

// auto-refresh/app.js
document.getElementById("container").textContent = "APP APP HOT ";
console.log("OK");

// auto-refresh/server.js
var webpack = require('webpack');
var config = require('./webpack.config.js');
var WebpackDevServer = require("webpack-dev-server");

var compiler = webpack(config);
new WebpackDevServer(webpack(config), {
    publicPath: config.output.publicPath,
    hot: true,
    noInfo: false,
    historyApiFallback: true
}).listen(8080, 'localhost', function (err, result) {
    if (err) {
        console.log(err);
    }
    console.log('Listening at localhost:3000');
});

// auto-refresh/webpack.config.js
/**
 * webpack打包配置文件
 */

var webpack = require('webpack');

module.exports = {
    entry : [
        'webpack-dev-server/client?http://127.0.0.1:8080', // WebpackDevServer host and port
        'webpack/hot/only-dev-server',
        './app.js'
    ],
    output : {
        path : './assets/',
        filename : '[name].bundle.js',
        publicPath : './assets/'
    },
    module : {
        loaders : [
            { test : /\.js$/, loader : 'react-hot!babel' },
            { test : /\.css$/, loader : 'style!css' }
        ]
    },
    plugins : [
        new webpack.HotModuleReplacementPlugin(),
        new webpack.NoErrorsPlugin(),
        new webpack.DefinePlugin({
            'process.env.NODE_ENV': '"development"'
        }),
    ]
};

// auto-refresh/index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>basic webpack</title>
</head>
<body>
    <div id="container"></div>
    <script src="./assets/main.bundle.js"></script>
</body>
</html>

// 運行
node server.js

// 瀏覽器輸入:localhost:8080

5.7 讓wepack.config.js支持es6寫法

// 1. 安裝babel-core、babel-preset-es2015以及babel-loader

// 2. 項目根目錄下配置.babelrc文件
{
  "presets": ["es2015"]
}

// 3. 將webpack.config.js從新命名爲webpack.config.babel.js

// 4.運行webpack --config webpack.config.babel.js

// 說明node 版本5.0以上,babel-core版本6以上須要如此配置

這是一個 Webpack 支持,但文檔裏徹底沒有提到的特性 (應該立刻就會加上)。只要你把配置文件命名成 webpack.config.[loader].js ,Webpack 就會用相應的 loader 去轉換一遍配置文件。因此要使用這個方法,你須要安裝 babel-loader 和 babel-core 兩個包。記住你不須要完整的 babel 包。

其餘辦法(未成功)

1.在上述的方案中,其實不須要從新命名就能夠直接運行webpack,可是今天試了一直不成功
2.{ 
    test : /\.js|jsx$/, 
    loader : 'babel',
    query: {
          //添加兩個presents 使用這兩種presets處理js或者jsx文件
          presets: ['es2015', 'react']
    } 
}

6.相關連接

webpack官方網站

用 ES6 編寫 Webpack 的配置文件

一小時包教會 —— webpack 入門指南

Webpack傻瓜式指南(一)

前端模塊化工具-webpack

如何開發一個 Webpack Loader ( 一 )

關於externals解釋

webpack使用優化

http://webpack.github.io/docs/installation.html

https://github.com/petehunt/webpack-howto

相關文章
相關標籤/搜索