webpack1 新手入門教程


本文github倉庫地址: https://github.com/Rynxiao/webpack-tutorial ,里面包括了本教程的所有代碼。

【如果你覺得這篇文章寫得不錯,麻煩給本倉庫一顆星:-D】

1. 導語

1.1 什么叫做webpack

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

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

1.2 webpack可以做一些什么事情

這里寫圖片描述

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

  • 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包會快上很多,具體做法:

// 方式一
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命令的時候,默認會執行這個文件)

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對應解析各個模塊時需要的加載器

一個簡單的例子

basic/app.js

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM