本文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

webpack1 新手入门教程的更多相关文章

  1. 安卓自动化测试(2)Robotium环境搭建与新手入门教程

    Robotium环境搭建与新手入门教程 准备工具:Robotium资料下载 知识准备: java基础知识,如基本的数据结构.语法结构.类.继承等 对Android系统较为熟悉,了解四大组件,会编写简单 ...

  2. Xorboot-UEFI新手入门教程

    Xorboot-UEFI新手入门教程        Xorboot-UEFI是一款UEFI下轻量级的图形化多系统引导程序,pauly于2014年国庆节期间发布了预览版.搜了下论坛,关于Xorboot- ...

  3. gulp的使用以及Gulp新手入门教程

    Gulp新手入门教程 原文  http://w3ctrain.com/2015/12/22/gulp-for-beginners/ Gulp 是一个自动化工具,前端开发者可以使用它来处理常见任务: 搭 ...

  4. 【LaTeX】E喵的LaTeX新手入门教程(6)中文

    假期玩得有点凶 ._.前情回顾[LaTeX]E喵的LaTeX新手入门教程(1)准备篇 [LaTeX]E喵的LaTeX新手入门教程(2)基础排版 [LaTeX]E喵的LaTeX新手入门教程(3)数学公式 ...

  5. 【LaTeX】E喵的LaTeX新手入门教程(4)图表

    这里说的不是用LaTeX画图,而是插入已经画好的图片..想看画图可以把滚动条拉到底.前情回顾[LaTeX]E喵的LaTeX新手入门教程(1)准备篇 [LaTeX]E喵的LaTeX新手入门教程(2)基础 ...

  6. 【LaTeX】E喵的LaTeX新手入门教程(5)参考文献、文档组织

    这不是最后一篇,明天开始建模所以会从6号开始继续更新.前情回顾[LaTeX]E喵的LaTeX新手入门教程(1)准备篇 [LaTeX]E喵的LaTeX新手入门教程(2)基础排版 [LaTeX]E喵的La ...

  7. 【LaTeX】E喵的LaTeX新手入门教程(3)数学公式

    昨天熄灯了真是坑爹.前情回顾[LaTeX]E喵的LaTeX新手入门教程(1)准备篇 [LaTeX]E喵的LaTeX新手入门教程(2)基础排版上一期测试答案1.大家一开始想到的肯定是\LaTeX{}er ...

  8. 【LaTeX】E喵的LaTeX新手入门教程(1)准备篇

    昨天熄灯了真是坑爹.前情回顾[LaTeX]E喵的LaTeX新手入门教程(1)准备篇 [LaTeX]E喵的LaTeX新手入门教程(2)基础排版上一期测试答案1.大家一开始想到的肯定是\LaTeX{}er ...

  9. 【LaTeX】E喵的LaTeX新手入门教程(2)基础排版

    换了块硬盘折腾了好久..联想的驱动真坑爹.前情回顾[LaTeX]E喵的LaTeX新手入门教程(1)准备篇文档框架嗯昨天我们已经编写了一个最基本的文档,其内容是这样的:\documentclass{ar ...

随机推荐

  1. slideToggle+slideup实现手机端折叠菜单效果

    折叠菜单的效果,网上有很多的插件,比如bootstrap的 Collapse ,很好用也很简单,但是如果你使用的不是bootstrap框架,就会造成很多不必要的麻烦,比如默认样式被修改,代码冗余等等, ...

  2. 图的M着色问题

    问题描述: 给定无向连通图 G 和 m 种不同的颜色.用这些颜色为图 G 和各顶点着色,每个顶点着一种颜色.是否有一种着色法使得图 G 中每条边的两个顶点着不同的颜色.这个问题是图的 m 可着色判定问 ...

  3. 使用babel编译es6

    起因:开发中慢慢的学习使用es6,但是JavaScript需要浏览器来解析,而不是所有浏览器都支持es6,所以为了兼容es6,需要第三方工具进行编译es6. 工具:node,gulp,gulp-bab ...

  4. Virtualbox让kali虚拟机共享主机的无线网络连接

    今天在测试虚拟机下安装kali系统时,遇到一个问题,默认安装完kali系统后,虚拟机不能上网.虚拟机网络配置使用的是默认的网络地址转换(NAT)选项. 网上查了很多,都说使用NAT模式时虚拟机不用做任 ...

  5. netty基础--基本收发

    使用maven构建一个基本的netty收发应用,作为其他应用的基础.客户端使用packet sender工具. 1  添加netty依赖 1  maven netty依赖 <dependency ...

  6. 从计算机语言的发展到我的第一行代码(HelloWorld)

    程序:为了让计算机执行某些操作或解决某个问题而编写的一系列有序指令的集合 算法:解决问题的具体方法和步骤 流程图是算法的一种图形化表示方式. 流程图直观.清晰,更有利于人们设计与理解算法. 它使用一组 ...

  7. 软件raid 5

    软件raid 5的实现 RAID 5 是一种存储性能.数据安全和存储成本兼顾的存储解决方案. RAID 5可以理解为是RAID 0和RAID 1的折中方案.RAID 5可以为系统提供数据安全保障,但保 ...

  8. dedecms列表页调用子栏目列表,织梦首页调用栏目的子栏目标签代码

    dedecms列表页调用子栏目列表,织梦首页调用栏目的子栏目标签代码. dedecms列表页调用子栏目列表标签: {dede:channelartlist type='sun' }<a href ...

  9. xssless - 自动化的XSS payload攻击器

    XSSLESS 一个用Python编写的自动化XSS 负载(payload)攻击器 用法: 记录请求 并结合Burp proxy 选择你想生成的请求,然后右键选择“保存项目” 使用xssless生成你 ...

  10. FastReport.NET 中使用二维码

    FastReport.net 是一个比较好用的报表控件,在编辑器中编辑以后 可以直接在vs 中引用. 最近在研究fastreport 现在讲解一下 如何使用它的二维码. fastreport 没有单独 ...