什么是 Webpack?

简单来说,Webpack 就是一个针对 JavaScript 代码的模块打包工具。

工作方式的对比

  • gulp:
    clipboard.png

  • webpack
    clipboard.png

gulp是工具链、构建工具,可以配合各种插件做js压缩,css压缩,less编译 替代手工实现自动化工作
如果我们日常使用的时候,不需要使用模块化这个概念,开发的JS随便在一个JS里就OK的情况,或者没有什么联动性的作用,可以使用sublime+gulp+browersync+babel
webpack利用模块化的概念,基本上统统都用js来写,Webpack的处理速度更快更直接,能打包更多不同类型的文件。

安装

首先创建一个webpackdemo的文件夹,然后命令行进入到该文件夹下,执行npm init,然后一路回车,输入yes后就可以看到文件夹下的package.json文件,这也是我们所有包都需要的文件依赖。

//全局安装
npm install -g webpack  --registry=http://registry.npm.taobao.org
//安装到你的项目目录
npm install --save-dev webpack  --registry=http://registry.npm.taobao.org

先来创建三个文件,一个是html,一个是我们即将使用的主入口文件index.js,一个是我们将要引用的文件person.js

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<script src="./build/bundle.js"></script>
</body>
</html>

//index.js
import Person from './second';

let app  = document.createElement('div');
app.className='MyDiv';
app.innerHTML = '<h1>Hello World,I am the index content</h1><h2>Hi,I am the vice content<h2>';
let luren = new Person('张三',18);
document.body.appendChild(app);
console.log(luren.say());

//second.js
class Person{
  constructor(name, age){
    this.name = name;
    this.age = age;
  }
  say(){
    return `我是${this.name},我今年${this.age}岁了。`;
  }
}
export default Person;

配置webpack.config.js文件

光有了package.json还不够,为了更方便,不用自己每次都去输入各种命令,还要有webpack.config.js文件

// entry 入口文件 让webpack用哪个文件作为项目的入口
// output 出口 让webpack把处理完成的文件放在哪里
// module 模块 要用什么不同的模块来处理各种类型的文件

var path = require('path');

//定义了一些文件夹的路径
var ROOT_PATH = path.resolve(__dirname);
var APP_PATH = path.resolve(ROOT_PATH, 'src');
var BUILD_PATH = path.resolve(ROOT_PATH, 'build');

module.exports = {
  //项目的文件夹 可以直接用文件夹名称 默认会找index.js 也可以确定是哪个文件名字
  entry: APP_PATH,
  //输出的文件名 合并以后的js会命名为bundle.js
  output: {
    path: BUILD_PATH,
    filename: 'bundle.js'
  },
  //webpack使用loader的方式来处理各种各样的资源/2.0叫rules,区别不是很大,任何文件运行想要解析都需要经过loader
  module: {
    rules: [
      {
        test: /\.jsx?$/,//首先先去匹配我们的include文件夹下的包含.js或.jsx后缀名的文件
        include: APP_PATH,//目标文件夹
        use: ['babel-loader']//使用babel-loader处理这些文件
      }
    ]
  },
};

以上就是一个最简单的webpack.config.js配置文件,其中loaders部分里只写了一个babel,就是为了我们能快点先看到东西,所以我们要先装上babelnpm install babel-core babel-loader babel-preset-latest --save-dev --registry=http://registry.npm.taobao.org
这里babel-core顾名思义是babel的核心编译器. babel-preset-latest是一个配置文件, 意思是转换ES2015/ES2016/ES2017到ES5, 不只ES6. babel还有其他配置文件. 如果只想用ES6, 可以安装babel-preset-es2015:
执行webpack,我们可以看到build里多了一个文件bundle.js,但是只有文件,这样的话没有服务器也是很麻烦,每次改动都需要手动执行webpack。而webpack自带的一个强大的功能就是自带开发服务器。

配置webpack-dev-server

npm install webpack-dev-server --save-dev --registry=http://registry.npm.taobao.org

安装完成后,如何使用它呢,肯定是要在配置文件里写上dev-server的配置的

// devserver配置选项   功能描述
// port    设置默认监听端口,如果省略,默认为”8080“
// inline  设置为true,当源文件改变时会自动刷新页面
// colors  设置为true,使终端输出的文件为彩色的
// historyApiFallback  在开发单页应用时非常有用,它依赖于HTML5 history API,如果设置为true,所有的跳转将指向index.html

module.exports = {
  ....
  devServer: {
    host:'0.0.0.0',//有了这个参数,写上0.0.0.0,我们就可以用ip地址访问了,没有的话如果别人访问会被禁止掉的
    historyApiFallback: true,
    hot: true,
    inline: true,
    //progress: true, 已经废弃,别写上去
  },
  ...
}

现在配置文件也有了,我们就可以走一把,运行webpack-dev-server --hot --inline。然后把我们的html文件中的script标签中的src给改掉<script src="http://localhost:8080/bundle.js"></script>,任意改动文件,就可以看到效果了。这个时候,有的同学说自己记不住这个命令怎么办。那么就把这命令写进package.json里面吧。

// npm的start是一个特殊的脚本名称,它的特殊性表现在,在命令行中使用npm start就可以执行相关命令,
// 如果对应的此脚本名称不是start,想要在命令行中运行时,需要这样用npm run {script name}如npm run build
...
"scripts": {
  "start": "webpack-dev-server --hot --inline"
},
...

下面是webpack-dev-server里的一些具体参数,可以看看。
clipboard.png

添加css和图片处理的loader/rule

npm install css-loader style-loader --save-dev --registry=http://registry.npm.taobao.org
然后修改下webpack.config.js的配置文件

//css-loader会遍历css文件,找到所有的url(...)并且处理
//style-loader会把所有的样式插入到你页面的一个style tag中
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader'],
        include: APP_PATH
      }

但是现在很多小伙伴又都喜欢使用less或者是sass,以less为例子,运行npm install less-loader less --save-dev --registry=http://registry.npm.taobao.org,然后再rule中修改正则和use也就是1.x版本中的loaders

      {
        test: /\.css|.less$/,
        use: ['style-loader', 'css-loader','less-loader'],//一旦use参数里的loader是一个数组,记住,执行顺序是从右向左,如果写错了那就会有问题了。
        include: APP_PATH
      }

css里面也可以模块化的引用其他css,@import 'xxx.less';,记住,一定要打分号,不像是js是弱类型可以不带,这个不带回报错的。
处理完了css/less,现在我需要引用图片了,怎么办,假如我在样式里写了网络路径的图片,是没有问题的,但是假如我随便写了一个本地路径的图片

.MyDiv{
    background: url('./img/smallPic.png');
}

运行会发现报错了,错误信息是

clipboard.png
还是很清楚的,它说它需要单独处理该文件的话需要我们弄一个loader也就是rules来处理他们
执行npm install url-loader file-loader --save-dev --registry=http://registry.npm.taobao.org,然后添加处理图片的loader

{
        /*
        css-loader引用的图片和字体同样会匹配到这里的test条件
        */
        test: /\.(png|jpg|jpeg|gif|eot|ttf|woff|woff2|svg|svgz)(\?.+)?$/,
        /*
        使用url-loader, 它接受一个limit参数, 单位为字节(byte)

        当文件体积小于limit时, url-loader把文件转为Data URI的格式内联到引用的地方
        当文件大于limit时, url-loader会调用file-loader, 把文件储存到输出目录, 并把引用的文件路径改写成输出后的路径
        */
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 10000
            }
          }
        ]
      },

然后没讲的是css的autoprefix功能,直接用你的编辑器快速补全吧,很方便的

其他功能

使用webpack2 自带的处理es6

{
  "babel": {
    "presets": [
      [
        "latest",
        {
          "es2015": {
            "loose": true,
            "modules": false
          }
        }
      ]
    ]
  }

使用后运行webpack可以发现bundle文件的行数会变小很多

使用自带的压缩js代码

plugins: [
    //这个使用uglifyJs压缩你的js代码,仅限生产环境,否则sourcemap找不到
    new webpack.optimize.UglifyJsPlugin({minimize: true})
  ]

可以看到这里使用了一个新的名词,plugins,就是一旦使用插件类的,都需要在plugins来写,很多写插件的话需要声明一个webpack。
在配置文件的最上面来写
var webpack = require('webpack');;

使用三方库比如jquery

    `npm install jquery --save-dev --registry=http://registry.npm.taobao.org`
    plugins: [
    ...
        new webpack.ProvidePlugin({
          $: "jquery",
          jQuery: "jquery",
          "window.jQuery": "jquery"
        })
    ...
    ]
    

分离第三方库

这个时候会发现我们的bundle.js文件超级大,因为jquery也被打进去了,所以我们需要做拆分工作,把我们引用的三方库给分离出来。

  entry: {
    app: APP_PATH,
    //添加要打包在vendors里面的库
    vendors: ['jquery']
  },
  //输出的文件名 合并以后的js会命名为bundle.js
  output: {
    path: BUILD_PATH,
    filename: '[name].js'
  },
  plugins: [
    ...
        new webpack.optimize.CommonsChunkPlugin({
                names: ['vendors']
         })
    ...
    ]
  

再手动把html引用的script给换掉就可以了。

使用source-map

clipboard.png

好多模式,该用哪个,开发用cheap-module-eval-source-map这个绝大多数情况下都会是最好的选择,这也是下版本 webpack 的默认选项。不方便看的话就直接source-map,就是文件大点

生产

建立生产配置文件webpack.production.config.js,然后去掉dev的配置,写进package.json"build": "webpack --progress --profile --colors --config webpack.production.config.js",运行npm run build即可


jansen
130 声望16 粉丝

学习不能止步,学习就是兴趣!终生学习是目标