官网
中文文档
中文文档
webpack
是目前前端工程化实践中最常用的打包工具,学习webpack
,有利于我们掌握前端模块化编程,也是我们在学习React
,Vue
等框架时做为重要支撑。
以下是官方和中文文档对webpack
的概括
At its core, webpack is a static module bundler for modern JavaScript applications. When webpack processes your application, it recursively builds a dependency graph that includes every module your application needs, then packages all of those modules into one or more bundles.
本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。
起步
安装
创建目录,初始化npm。
mkdir webpack-demo && cd webpack-demo
cnpm init
cnpm install webpack --save-dev
说明:
- cnpm是淘宝npm镜像,使用方法和
npm
一样。可以帮助我们提升包的下载速度。 -
cnpm install {packeg_name} --save-dev
,package_name
为要下载的包名称,--save-dev
,表示将package-name
添加到package.json
的devDependencies
中。
创建两个文件测试,index.html
,index.js
。
index.html
Getting Started
其中,bundle.js
是我们等会要生成的文件,先不用了解
index.js
function component() {
var element = document.createElement('div');
element.innerHTML = 'hello webpack'
return element;
}
document.body.appendChild(component());
此时的目录结构为:
webpack-demo
node_modules
src
index.js
index.html
package.json
将项目搭建成上述结构,我们就能学习第一个命令webpack
。我们的目标就是以index.js
为入口,生成一个bundle.js
文件,供index.html
使用。
webpack src/index.js dist/bundle.js
Hash: 629328b9dd2012d414f7
Version: webpack 3.10.0
Time: 59ms
Asset Size Chunks Chunk Names
bundle.js 2.64 kB 0 [emitted] main
[0] ./src/index.js 170 bytes {0} [built]
如果出现上诉回应,就说说明执行成功。此时我们的项目结构是这样的:
webpack-demo
dist
bundle.js
node_modules
src
index.js
index.html
package.json
可以看到dist/bundle.js
就是webpack
替我们生成的。
在浏览器中打开index.html
,可以看到hello webpack
。
我们来看bundle.js
究竟是个什么东西。
cat dist/bundle.js
//// 一堆被注释掉的代码
function component() {
var element = document.createElement('div');
element.innerHTML = 'hello webpack'
return element;
}
document.body.appendChild(component());
// 这段代码是我们是从我们的index.js copy的。
可以看到,对于我们自己写的函数,webpack
会原封不动的copy过来。
配置文件
我们之前使用的webpack src/index.js dist/bundle.js
其实可以使用一个配置文件来表述,比在终端中敲命令更加方便。
创建文件 webpack.config.js
此时:
node_modules
src
index.js
index.html
package.json
webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
说明:
- 其中,
require
是node.js内置函数表示引入模块,path
是node.js内置模块。 - entry是入口文件,就是我们的
index.js
。 - outpath表示输出目录及文件名。
为了便于观察,我们删掉之前生成的dist目录及其文件
。
我们执行命令:
webpack --config webpack.config.js
Hash: 629328b9dd2012d414f7
Version: webpack 3.10.0
Time: 59ms
Asset Size Chunks Chunk Names
bundle.js 2.64 kB 0 [emitted] main
[0] ./src/index.js 170 bytes {0} [built]
此时目录结构:
webpack-demo
dist
bundle.js
node_modules
src
index.js
index.html
package.json
在浏览器中查看index.html
,依然可以看到hello webpack
。
需要注意的是配置文件命名不一定是webpack.config.js
,可以自由命名,如果为webpack.config.js
,在使用命令时,可以省略--config
。
如果觉得输入webpack
比较麻烦或陌生,可以这样来使用:
在package.json
中加入如下代码:
{
"scripts":{
"build":"webpack"
}
}
以后我们在打包时,可以直接使用:
cnpm run build
以上是用webpack实现的最基本的构建过程。
可以看到,我们的index.html
是我们自己创建的,如果我们配置了多个入口文件或者修改了出口文件,自己再来修改index.html
是很麻烦的,我们使用一个插件:
cnpm install --save-dev html-webpack-plugin
plugins:[
new HtmlWebpackPlugin({
title:'webpack-demo'
})
]
我们删除根目录下我们自己手写的index.html
。
rm index.html
cnpm run build
dist
bundle.js
index.html
cat index.html
webpack-demo
我们发现,我们刚才安装的这个插件,已经帮我们书写好了index.html
。
且引入了打包产生的js文件。这是非常方便的。
管理资源
除了javascript
,还可以通过loader
引入其他类型的文件,如css
.
加载CSS
我们安装style-loader
cnpm install --save-dev style-loader css-loader
修改webpack.config.js
:
module:{
rules:[
{
test:/\.csss$/,
use:[
'style-loader',
'css-loader'
]
}
]
}
要严格按照如上写法,避免遇到问题。
通过浏览器预览,我们发现hello webpack
变成了红色。
加载图片
cnpm install --save-dev file-loader
修改webpack.config.js
:
{
test: /\.(png|svg|jpg|gif)$/,
use :[
'file-loader'
]
}
放入一张图片icon.png
到src
中。
修改index.js
:
import MyImg from './icon.png';
var img = new Image();
img.src = MyImg;
element.appendChild(img);
我们通过build
,发现此时我们的页面上显示了刚才添加的图片,这张图片被放在了dist
中。
管理输出
因为代码改的比较频繁,我们的dist目录中的文件会越来越多,有的文件可能不再需要,所以,在每次构建前清理dist
目录,是比较好的做法,因为只会生成用到的文件。
cnpm install clean-webpack-plugin --save-dev
修改webpack.config.js
:
const CleanWebpackPlugin = require('clean-webpack-plugin');
plugins:[
new CleanWebpackPlugin(['dist'])
]
此时,执行build
后,dist
中的文件就不会再有不需要的文件了。
开发
现在我们有一个痛点,每次修改代码后,要手动重新webpack,才能查看改动后的情况
,其实webpack给我们提供了多个方案,让我们在代码发生变化后自动编译代码:
- webpack watch mode
- webpack dev server
- webpack dev middleware
需要指出的是,这三种方案都比较常用,特别是在一些项目的脚手架中,都高频使用这些项目,比如vue-cli
。
观察者模式
修改package.json
:
{
scripts:{
"watch":"webpack --watch"
}
}
此时,我们在终端中输入:
`cnpm run watch`
> [email protected] watch /Users/liuhao/Desktop/webpack-demo
> webpack --watch
clean-webpack-plugin: /Users/liuhao/Desktop/webpack-demo/dist has been removed.
Webpack is watching the files…
Hash: a6eb44b735ce8b5f1f68
Version: webpack 3.10.0
Time: 689ms
Asset Size Chunks Chunk Names
22f56d054f6abc3b0683e95a6a3f5150.png 95.6 kB [emitted]
bundle.js 20.3 kB 0 [emitted] main
index.html 183 bytes [emitted]
[0] ./src/icon.png 82 bytes {0} [built]
[1] ./src/index.js 333 bytes {0} [built]
[2] ./src/style.css 1.04 kB {0} [built]
[3] ./node_modules/.0.28.9@css-loader!./src/style.css 330 bytes {0} [built]
+ 4 hidden modules
Child html-webpack-plugin for "index.html":
1 asset
[2] (webpack)/buildin/global.js 509 bytes {0} [built]
[3] (webpack)/buildin/module.js 517 bytes {0} [built]
+ 2 hidden modules
Hash: 0eb719c26b33a7a1afe0
Version: webpack 3.10.0
Time: 28ms
Asset Size Chunks Chunk Names
bundle.js 20.3 kB 0 [emitted] main
index.html 183 bytes [emitted]
+ 1 hidden asset
[1] ./src/index.js 337 bytes {0} [built]
+ 7 hidden modules
Child html-webpack-plugin for "index.html":
1 asset
4 modules
可以看到webpack
watch
模式开启后,webpack
进程没有退出,一直在监听程序变动,我们手动改动某一个位置,webpack
又会自动编译。这种方式的弊端就是,我们要观察页面,还是得手动刷新浏览器。
webpack-dev-server
如果说webpack --wacth
只是webpack
自带的一个简单工具,那么webpack-dev-server
就非常有用了。它提供一个简单的web服务器,能够实时重新加载。webpack-dev-server
是webpack
的另外一个项目,且出自于官方。
cnpm install --save-dev webpack-dev-server
修改webpack.config.js
:
devServer:{
contentBase:'./dist'
}
修改package.json
:
{
scripts:{
"start":"webpack-dev-server --open"
}
}
此时,我们执行cnpm start
,就会在8080
端口起来一个服务。渲染出html页面。当我们修改代码后,server会自动编译,成功后会通知浏览器自动刷新,此时我们不要受到刷新浏览器,即可看到更新后的内容。
webpack-dev-middleware
与webpack-dev-server
一样,webpack-dev-middleware
也是由webpack
官方进行维护的,但是能进行更多的自定义设置。
安装express
和 webpack-dev-middleware
其中,express
是node.js
中优秀的web项目。
cnpm install --save-dev express webpack-dev-middleware
修改 webpack.config.js
:
output: {
publicPath:'/'
}
创建server.js
:
const express = require('express');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const app = express();
const config = require('./webpack.config.js');
const compiler = webpack(config);
// Tell express to use the webpack-dev-middleware and use the webpack.config.js
// configuration file as a base.
app.use(webpackDevMiddleware(compiler, {
publicPath: config.output.publicPath
}));
// Serve the files on port 3000.
app.listen(3000, function () {
console.log('Example app listening on port 3000!\n');
});
node.js server会启动在3000端口。
我们添加一项script来快速启动server.js
.
{
“scripts”:{
"server":"node server.js"
}
}
了解node.js
的同学都知道node
命令用来干啥,不在赘述。
现在我们执行:
cnpm run server
此时也实现了自动编译,如果还希望同步到浏览器,还需要使用另外一个项目,webpack-hot-middleware
。
以上,我们可以知道,webpack-dev-server
是使用起来最方便的。
这些内容,可以帮助我们在开发中,做到心中有数,后面我将结合es6+vue.js+webpack
来演示单页应用的开发。