webpack的实例


这是收集的一些简单的webpack实例演示,
这些演示是故意写的一个简单明了的风格,对于学习这个强大的工具,你将发现没有困难

本文参考:阅读原文
建议阅读原文,因为本文有修改,省略。。。

如何使用

全局安装Webpackwebpack-dev-server

npm i -g webpack webpack-dev-server

克隆项目到你的电脑,并安装依赖

1
2
3
4
5
6
7
8
# Linux & Mac
git clone git@github.com:vichily/webpack-demos.git

# Windows
git clone https://github.com/vichily/webpack-demos.git
:
cd webpack-demos
npm install

切换目录到demo,启动服务

1
2
cd demo01
webpack-dev-server

在浏览器输入http://127.0.0.1:8080

Demo01————入口文件

入口文件是webpack读取并要构造的一个文件
例如demo1,main.js是一个入口文件

1
2
3
4
5
6
7
// webpack.config.js
module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js'
}
};

启动服务器,访问http://127.0.0.1:8080

Demo02————多个入口文件

对于多页面的应用,允许多个入口文件。
可以是对象格式或者数组格式

1
2
3
4
5
6
7
8
9
module.exports = {
entry: {
bundle1: './main1.js',
bundle2: './main2.js'
},
output: {
filename: '[name].js'
}
};

Demo03————Babel-加载器

加载器能将程序的资源文件预处理,例如Babel-加载器,可以转换JSX/ES6的文件,官方文档上有完整的加载器列表http://webpack.github.io/docs/list-of-loaders.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
module.exports = {
entry: './main.jsx',
output: {
filename: 'bundle.js'
},
module: {
loaders:[
{
test: /\.js[x]?$/,
exclude: /node_modules/,
loader: 'babel-loader?presets[]=es2015&presets[]=react'
},
]
}
};

在webpack.config.js,module.loaders字段用于指定加载器
上面的代码片段使用babel加载器需要的插件是babel-preset-es2015babel-preset-react来处理ES6和React
也可以用另外一种写法

1
2
3
4
5
6
7
8
9
10
11
12
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel',
query: {
presets: ['es2015', 'react']
}
}
]
}

启动服务器,访问http://127.0.0.1:8080

Demo04————CSS-加载器

Webpack允许将css引入js文件,然后用css加载器预处理CSS文件。

1
2
<!-- main.js -->
require('./app.css');

1
2
3
4
5
6
7
8
9
10
11
12
<!-- 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插入css到html的style标签中,不同的加载器之间用感叹号(!)

Demo05————Image-加载器

Webpack 也能在js中加载图片

1
2
3
4
5
6
7
8
<!-- 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);
1
2
3
4
5
6
7
8
9
10
11
12
<!-- webpack.config.js -->
module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js'
},
module: {
loaders:[
{ test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192' }
]
}
};

url-加载器转换图像文件,如果图像的大小小于8192字节,它将被转换成数据的网址,否则,它将被转换成正常的网址。如你所见,问号(?)用于将参数传递到装入器中。

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

Demo06————Css-模块

css-loader?modules 的参数说明在这里https://github.com/css-modules/css-modules
Css模块默认是本地作用域,可以设置:global()来处理选择器和规则,则变为全局的,更多实例

1
2
3
4
5
6
7
8
<html>
<body>
<h1 class="h1">Hello World</h1>
<h2 class="h2">Hello Webpack</h2>
<div id="example"></div>
<script src="./bundle.js"></script>
</body>
</html>

1
2
3
4
5
6
7
.h1 {
color:red;
}

:global(.h2) {
color: blue;
}
1
2
3
4
5
6
7
8
9
10
11
12
<!-- main.jsx -->
var React = require('react');
var ReactDOM = require('react-dom');
var style = require('./app.css');

ReactDOM.render(
<div>
<h1 className={style.h1}>Hello World</h1>
<h2 className="h2">Hello Webpack</h2>
</div>,
document.getElementById('example')
);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!-- webpack.config.js -->
module.exports = {
entry: './main.jsx',
output: {
filename: 'bundle.js'
},
module: {
loaders:[
{
test: /\.js[x]?$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['es2015', 'react']
}
},
{
test: /\.css$/,
loader: 'style-loader!css-loader?modules'
}
]
}
};

启动服务器,访问http://127.0.0.1:8080
你会发现只有第二个H1是红色的,因为它的CSS是局部范围,H2是都是蓝色的,因为它是全局内的CSS。

Demo07————UglifyJs-插件

Webpack有一个插件系统来扩展其功能,例如,UglifyJs Plugin将压缩js代码

1
2
3
4
<!-- main.js -->
var longVariableName = 'Hello';
longVariableName += ' World';
document.write('<h1>' + longVariableName + '</h1>');

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!-- 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
}
})
]
};

启动服务后,main.js将压缩为以下js

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

Demo08————HTML Webpack Plugin 和 Open Browser Webpack Plugin

本演示展示了如何加载第三方插件。
html-webpack-plugin可以创建index.html,Open Browser Webpack Plugin可以打开一个浏览器页面加载内容

1
2
<!-- main.js -->
document.write('<h1>Hello World</h1>');

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- 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————Environment flags

只有在开发环境中通过环境标志,才能使用的一些代码

1
2
3
4
5
6
<!-- main.js -->
document.write('<h1>Hello World</h1>');

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- 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设置环境变量

1
2
3
4
5
6
# Linux & Mac
$ env DEBUG=true webpack-dev-server

# Windows
set DEBUG=true
webpack-dev-server

Demo10————代码拆分

大型的web应用程序不能有效的把所有代码放到一个单独的文件,特别是如果一些代码块只有在需要的情况下的时候才被加载,webpack可以分割成几块
首先,你用require.ensure定义一个分割点

1
2
3
4
5
6
7
<!-- main.js -->
require.ensure(['./a'], function(require) {
var content = require('./a');
document.open();
document.write('<h1>' + content + '</h1>');
document.close();
});

require.ensure告诉webpack,/ a.js应该分开,和bundle.js形成单块文件。

1
2
<!-- a.js -->
module.exports = 'Hello World';

现在没有任何的冗余到index.html和webpack.config.js中
在表面上,你不会觉得有什么差异。实际上,main.js 和 a.js构建成不同的块

Demo11————bundle-loader代码拆分

另一种代码拆分的方式是使用bundle-loader

1
2
3
4
5
6
7
8
<!-- main.js -->
var load = require('bundle-loader!./a.js');

load(function(file) {
document.open();
document.write('<h1>' + file + '</h1>');
document.close();
});

require(‘bundle-loader!./a.js’) 告诉Webpack从另一个块加载a.js。
现在Webpack将建立main.js为bundle.js,a.js为1.bundle.js。

Demo12————公有块

当多个脚本有共同的部分,可以用CommonsChunkPlugin提取公共部分为一个单独的文件

1
2
3
4
5
6
7
8
<!-- main1.jsx -->
var React = require('react');
var ReactDOM = require('react-dom');

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

1
2
3
4
5
6
7
8
<!-- main2.jsx -->
var React = require('react');
var ReactDOM = require('react-dom');

ReactDOM.render(
<h2>Hello Webpack</h2>,
document.getElementById('b')
);
1
2
3
4
5
6
7
8
9
10
<!-- indwx.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>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!-- 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')
]
}

Demo13————Vendor chunk(供应商的块???怪怪的)

你也可以把脚本中所引用的库编译到一个单独的文件中(比如把引用jquery模块单独放到一个文件中)

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

1
2
3
4
5
6
7
8
<!-- index.html -->
<html>
<body>
<h1></h1>
<script src="vendor.js"></script>
<script src="bundle.js"></script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//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来使用模块jQuery,你应该使用ProvidePlugin

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 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"
})
]
};

Demo14————公开全局变量

如果你想使用一些全局变量,而不想包括在webpack包中,您可以在webpack.config.js启用外部字段
例如:我们有一个data.js

1
var data = 'Hello World';

我们可以将数据公开为一个全局变量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// webpack.config.js
module.exports = {
entry: './main.jsx',
output: {
filename: 'bundle.js'
},
module: {
loaders:[
{
test: /\.js[x]?$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['es2015', 'react']
}
},
]
},
externals: {
// require('data') is external and available
// on the global var data
'data': 'data'
}
};

现在,在你的脚本中引入这个data模块。但它实际上是一个全局变量。

1
2
3
4
5
6
7
8
9
// main.jsx
var data = require('data');
var React = require('react');
var ReactDOM = require('react-dom');

ReactDOM.render(
<h1>{data}</h1>,
document.body
);

Demo15————Hot Module Replacement(热插拔)

Hot Module Replacement (HMR)可以在程序运行时候,无需重新加载页面交换、添加、删除模块
您有两种方法在webpack-dev-server中来启用Hot Module Replacement(热插拔)

  • 1、通过指令webpack-dev-server –hot –inline
    • –hot: adds the HotModuleReplacementPlugin and switch the server to hot mode.
    • –inline: embed the webpack-dev-server runtime into the bundle.
    • –hot –inline: also adds the webpack/hot/dev-server entry.
  • 2、修改webpack.config.js.
    • add new webpack.HotModuleReplacementPlugin() to the plugins field
    • add webpack/hot/dev-server and webpack-dev-server/client?http://localhost:8080 to the entry field

webpack.config.js看起来就像下面这个样子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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, '.')
}]
}
};

现在启动开发服务器
打开 http://localhost:8080,你将在浏览器中看到’Hello World’
不要关闭服务器。打开app.js编辑,并修改“Hello World”变成“你好webpack”。保存它,看看在浏览器中发生了什么。

1
2
3
4
5
6
7
8
9
10
//App.js
import React, { Component } from 'react';

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

1
2
3
4
5
6
//index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(<App />, document.getElementById('root'));
1
2
3
4
5
6
7
<!-- index.html -->
<html>
<body>
<div id='root'></div>
<script src="/static/bundle.js"></script>
</body>
</html>

Demo16————React 路由

在后面有文章会介绍
> +———————————————————+
| +———+ +——-+ +——–+ |
| |Dashboard| | Inbox | |Calendar| Logged in as Jane |
| +———+ +——-+ +——–+ |
+———————————————————+
| |
| Dashboard |
| |
| |
| +———————+ +———————-+ |
| | | | | |
| | + + | +———> | |
| | | | | | | |
| | | + | | +————-> | |
| | | | + | | | | |
| | | | | | | | | |
| +-+—+—-+—–+—-+ +———————-+ |
| |
+———————————————————+