webpack

官网
中文文档
中文文档
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.jsondevDependencies中。

创建两个文件测试,index.htmlindex.js

index.html

<html>
  <head>
    <title>Getting Started</title>
  </head>
  <body>
    <script src="./dist/bundle.js"></script>
  </body>
</html>

其中,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
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>webpack-demo</title>
  </head>
  <body>
  <script type="text/javascript" src="bundle.js"></script></body>
</html>

我们发现,我们刚才安装的这个插件,已经帮我们书写好了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.pngsrc中。
修改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`
> webpack-demo@1.0.0 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-serverwebpack的另外一个项目,且出自于官方。

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官方进行维护的,但是能进行更多的自定义设置。

安装expresswebpack-dev-middleware
其中,expressnode.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来演示单页应用的开发。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 227,488评论 6 531
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 98,034评论 3 414
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 175,327评论 0 373
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 62,554评论 1 307
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 71,337评论 6 404
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 54,883评论 1 321
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 42,975评论 3 439
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 42,114评论 0 286
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 48,625评论 1 332
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 40,555评论 3 354
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 42,737评论 1 369
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 38,244评论 5 355
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 43,973评论 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 34,362评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 35,615评论 1 280
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 51,343评论 3 390
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 47,699评论 2 370