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


  
    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.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`
> [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-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来演示单页应用的开发。

你可能感兴趣的:(webpack)