本文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
就會生成帶有chunkhash
的chunk
文件,如下圖:
這在做給文件打版本號的時候特別有用,當時如何進行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
中的include
與exclude
include
表示必須要包含的文件或者目錄,而exclude
的表示需要排除的目錄
比如我們在配置中一般要排除node_modules
目錄,就可以這樣寫
{
test : /\.js$/,
loader : 'babel',
exclude : nodeModuleDir
}
官方建議:優先采用include,並且include最好是文件目錄
4.3.3 module.noParse
使用了noParse
的模塊將不會被loaders
解析,所以當我們使用的庫如果太大,並且其中不包含require
、define
或者類似的關鍵字的時候(因為這些模塊加載並不會被解析,所以就會報錯),我們就可以使用這項配置來提升性能。
例如下面的例子:在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.js
、app2.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']
}
}