码迷,mamicode.com
首页 > Web开发 > 详细

webpack学习笔记

时间:2015-08-02 18:18:14      阅读:173      评论:0      收藏:0      [点我收藏+]

标签:webpack

是什么

webpack是一个模块打包工具,通过依赖处理模块,并生成那些模块静态资源。
技术分享
观察上图,webpack把所有的资源(js,css和图片等)都当做是模块——webpack中可以引用css,css中可以嵌入图片dataUrl,对于不同类型的资源,webpack有对应的模块加载器。webpack模块打包器会分析模块间的依赖关系,最后 生成了优化且合并后的静态资源。


为什么

当今网站正在变成一个web应用:一个页面包含的javascript代码越来越多,结果客户端存在着大量的代码。通过模块系统划分代码到一个个小模块中,是管理大量代码的有效方式。目前有好几种方式用于实现模块和依赖关系定义:

  • <script>标签

    • 简介:这是最基本的代码模块化方式,这种模块输出方式会暴露接口道一个全局对象,即window,需要通过全局对象来访问依赖的模块。
    • 实例:

      <script src="module1.js"></script>
      <script src="module2.js"></script>
      <script src="libraryA.js"></script>
      <script src="module3.js"></script>
    • 缺点
      • 不同模块容易发生 冲突
      • 加载顺序依赖script标签的顺序
      • 在一个大项目中,script标签列表可能变得很长,难以管理
  • CommonJS

    • 简介:CommonJS使用同步的require方法加载依赖模块——模块可以通过给exports对象绑定属性或者给module.exports赋值来定义输出,
    • 实例:

      require("module");
      require("../file.js");
      exports.doStuff = function() {};
      module.exports = someValue;
    • 优点
      • 服务端模块可以重用?
      • 这种方式开发的模块有很多(NPM)
      • 非常简单,很容易使用
    • 缺点
      • 阻塞式的调用不适用于网络(网络请求是异步的)
      • 不能并发请求多个模块
    • 实现
  • AMD

    • 简介:AMD是异步版本的模块CommonJS
    • 实例:

      require(["module", "../file"], function(module, file) { /* ... */ });
      define("mymodule", ["dep1", "dep2"], function(d1, d2) {
          return someExportedValue;
      });
    • 优点
      • 实现了异步请求方式
      • 并行加载多个模块
    • 缺点
      • 代码读写起来比较吃力
      • 看起来像个变通方案
    • 实现
  • ES6

    • 简介:EcmaScript6给Javascript增加了一些语法,形成了另外一种模块系统
    • 实例:

      import "jquery";
      export function doStuff() {}
      module "localModule" {}
    • 优点
      • 静态分析很简单?
      • ES标准,不会过时

模块确定了,要在客户端执行,必须从服务器传输到客户端。以下是两种极端的传输方式:

  • 一个请求一个模块
    • 优点:只传输请求的模块
    • 缺点:多个模块需要多次请求,影响性能,应用启动慢
  • 一次请求所有模块
    • 优点:较少的请求消耗
    • 缺点:不需要的模块也会被传输到客户端

上面两种模块加载方式比较极端,我们需要一个能够更加灵活地传输模块的方法。当在编译所有模块的时候,将整个系统划分成多个更小的模块集。各个模块集不会一开始就加载进来,只有在需要的时候才加载,所以初始化的时候并没有包含所有的模块代码。模块集的划分点取决于开发者,例如按功能划分,将该模块依赖的一个个模块当做一个模块集,当访问系统某项功能时,一次请求加载该项功能的模块集。

前面讨论完关于模块的定义与加载,我们发现为什么只提到了Javascript的模块系统,而前段还有许多其他的静态资源需要加载,如:样式表、图片、字体和html模板等。我们能不能像javascript一样使用require来加载指定的静态资源,例如:

require("./style.css");
require("./style.less");
require("./template.jade");
require("./image.png");

一个大点的项目,都会遇到上面的问题——模块划分和静态资源,目前已有的模块打包工具已经不适用了。而webpack作者曾尝试扩展已有的模块打包工具,但也是无法实现所有的构建目标。
webpack的目标:

  • 将所有模块划分成一个个子模块集,在需要的时候才加载
  • 保证较低的加载时间
  • 将每一个静态资源都当做一个模块
  • 能够以模块的方式集成第三方库
  • 能够定制模块打包的每一部分
  • 适用于大型项目

webpack的特性

  • 模块划分
    webpack不仅支持CommonJS——支持同步依赖,而且也支持AMD——支持异步依赖,也是模块划分点,形成一个新的模块集。
  • 加载器
    webpack只能加载本地的Javascript,通过一系列的加载器可以实现不同静态资源的加载。
  • 智能编译
  • 插件系统
    webpack有着丰富的插件系统,大多数内部特性都是基于插件系统。

安装使用

安装

  1. 安装node.js——node.js自带有一个模块管理器npm
  2. 安装webpack
    • 全局安装:npm install webpack -g,如果有将npm全局安装路径加入path,则可以直接在命令行输入webpack命令了
    • 本地安装:npm install webpack --save-d,本地安装后的命令行工具在./node_modules/.bin/webpack.cmd,也可以在npm package.json里的scripts里引用webpack

用法

除了在命令行界面使使用webpack外,也可以直接在代码中使用webpack。

  • 命令行界面
    • webpack --entry entry.js --output bundle.js
    • webpack --config webpack.config.js
    • webpack --config webpack.config.js -d:开发模式
    • webpack --config webpack.config.js -w:观察模式
    • webpack --config webpack.config.js -p:生成模式
  • node.js-api

    • 简单示例

      var webpack = require("webpack");
      // returns a Compiler instance
      webpack({
          // configuration
      }, function(err, stats) {
          // ...
      });
    • 复杂示例

      var webpack = require("webpack");
      
      // returns a Compiler instance
      var compiler = webpack({
          // configuration
      });
      
      compiler.run(function(err, stats) {
          // ...
      });
      // or
      compiler.watch({ // watch options:
          aggregateTimeout: 300, // wait so long for more changes
          poll: true // use polling instead of native watchers
          // pass a number to set the polling interval
      }, function(err, stats) {
          // ...
      });

常见问题:

  • webpack命令的--confgi选项是做什么的?
    --config用来指定一个配置文件,代替命令行中的选项,从而简化命令。如果直接执行webpack的话,webpack会在当前目录查找名为webpack.config.js的文件。

简单示例

本例展示Hello World!,源代码如下:

  • index.html

    <html>
        <head>
            <meta charset="utf-8">
        </head>
        <body>
            <script type="text/javascript" src="bundle.js" charset="utf-8"></script>
        </body>
    </html>
  • entry.js

    document.write(require("./content.js"));
  • content.js

    module.exports = "Hello World.";

模块打包及运行:

  1. 执行命令webpack ./entry.js bundle.js,该命令会编译entry.js和content.js,并合并生成一个bundle.js。
  2. 在浏览器中打开index.html,显示:Hello World!.

除了在webpack命令选项中指定模块入口文件和模块打包生成文件外,可以创建webpack.config.js来配置,具体配置如下代码所示。配置好后,在命令行中直接输入webpack(默认查找配置文件webpack.config.js)或者webpack --config webpack.config.js,这样效果同上面的命令webpack ./entry.js bundle.js

module.exports = {
    entry: "./entry.js",
    output: {
        path: __dirname,
        filename: "bundle.js"
    }
};

更多关于webpack.config.js的配置见下文。


模块详解

webpack同时支持CommonJS和AMD规范的模块编写方式, Hello World实例已经简单地演示了模块的定义和加载,下面我们开始学习webpack模块相关的api。

模块定义

  • module.exports

    • 简介:CommJS规范的模块定义,module.exports指定的对象作为模块的输出,没有指定的话默认返回一个新对象,即{}。
    • 实例:

      module.exports = function doSomething() {
          // Do something
      };
    • 总结:在加载module.exports格式定义的模块时,模块返回的是module.exports指定的对象
    • 注意点:不可以在异步函数中使用module.exports
  • exports

    • 简介:CommonJS规范的模块定义,exports是被输出的对象,如果已经指定了module.exports,则exports会被忽略
    • 实例:

      exports.someValue = 42;
      exports.anObject = {
          x: 123
      };
      exports.aFunction = function doSomething() {
          // Do something
      };
  • export label

    • 简介:Labeld模块定义格式
    • 实例:

      export: var answer = 42;
      export: function method(value) {
        // Do something
      };
    • 注意点:在异步函数中使用可能得不到想要的效果
  • define

    • 简介:AMD规范的模块定义
    • 语法:
      • define(value: !Function)
        • value 非函数值
      • define([name: String], [dependencies: String[]], factoryMethod: function(...))
        • name String 可选参数,表示模块名
        • dependencies String[] 可选参数,依赖的模块名数组
        • factoryMethod function 必填参数,该函数要求有个返回值,作为模块的输出
    • 示例

      • define with value

        define({
            answer: 42
        });
      • define with factory

        define(["jquery", "my-module"], function($, myModule) {
            // Do something with $ and myModule.
            // Export a function
            return function doSomething() {
                // Do something
            };
        });
    • 总结:
      • define没有指定模块名称的时候,默认使用模块所在文件路径和名称作为模块名称,通常推荐使用这个名称就行了,不要再自己指定模块名称。
      • define函数可以指定依赖的模块,需要注意的是这些模块是同步加载的——模块本身和dependencies模块在同一个模块集里,即,webpack构建生成后放到同一个文件里。
    • 注意点:不能在异步函数中使用

模块加载

  • require CommonJs
    • 简介:CommonJS规范的require,同步加载指定的模块。webpack编译器会确保客户端执行到这行代码的时候,依赖的模块已经可用,无需向服务器发送请求——实际上webpack就是把需要加载的模块代码和require合并到同一文件里了,所以无需再发送请求获取模块了。
    • 语法:require(dependency: String)
    • 参数
      • dependency:需要加载的模块名
    • 实例:HellowWorld实例的entry.js中存在这样一行代码document.write(require("./content.js"));,这便是一个commonJS规范的require。这里有两个模块:entry.js和content.js,执行webpack却只生成了一个文件bundle.js。
  • require label
    • 简介:同CommonJS,require label也是同步加载指定模块,只是require语法不通罢了——webpack编译器会处理这种语法
    • 语法:require: "dependency"
    • 实例:
    • 备注:注意require label需要借助插件webpack.dependencies.LabeledModulesPlugin,关于插件的使用,后续会介绍,暂时忽略,本节只是关注require label的写法
  • require AMD

    • 简介:AMD规范的require,异步加载指定的模块——在需要的时候(代码执行到AMD require)才会加载依赖的模块。
    • 语法:require(dependencies: String[], [callback: function(...)])
      • dependencies String[] 需要加载的模块名数组
      • callback function 回调函数,在所有模块加载后执行,dependencies指定的模块实例按参数定义的顺序传递给callback
    • 实例:

      // in file.js
      var a = require("a");
      var d = require("d);
      require(["b", "d"], function(b, d) {
        var c = require("c");
      });
      /* This results in:
          * entry chunk
              - file.js
              - a
              - d
          * anonymous chunk
              - b
              - c
      */
    • 总结:require AMD会影响webpack的模块打包结果,前面有提到AMD规范的模块依赖便是模块划分点。上例中执行webpack file.js bundle.js生成bundle.js和1.chunk.js,前者包含模块file.js、a.js和d.js,后者包含模块b.js和c.js。关于require AMD模块划分规则,如下所示:
      • dependencies的模块和callback中以CommonJS require的模块在之前都没有加载过,则webpack会将这些模块合并到同一个模块集里,生成一个chunk.js文件
      • dependencies的模块和callback中以CommonJS require的模块在之前有加载过,则加载过的模块会合并的之前的模块集里,本模块集不会包含这个模块,对于没有加载过的模块webpack处理同上
      • callback中以AMD require加载的模块按新的模块集处理
      • 关于如何判断一个模块是否有加载过?webpack编译器自己会处理模块间的依赖关系来分析,一个比较复杂的例子可以参考CommonsJs, AMD and labeled modules mixed
  • require.ensure

    • 简介:与require AMD类似,也是在需要的时候才会加载相应的模块。但不同的是,require.ensure在模块被下载下来后(模块还没被执行)便立即执行回调函数,另外require.ensure可以指定构建后chunk名,如果之前已有require.ensure指定了该名称,webpack会将这些模块统一合并到一个模块集里。
    • 语法:require.ensure(dependencies: String[], callback: function([require]), [chunkName: String])
    • 实例:

      • 简单示例:

        // in file.js
        var a = require("a");
        require.ensure(["b"], function(require) {
            var c = require("c");
        });
        require.ensure(["d"], function() {
            var e = require("e");
        }, "my chunk");
        require.ensure([], function() {
            var f = require("f");
        }, "my chunk");
        /* This results in:
            * entry chunk
                - file.js
                - a
            * anonymous chunk
                - b
                - c
            * "my chunk"
                - d
                - e
                - f
        */
        
      • code-splitted-require.context
      • require.ensure VS require AMD
    • 总结:除了require.ensure可以直接指定模块名外,require.ensure与require AMD一致,都可以进行代码划分,规则也一致。
  • require.include

    • 简介: 确保模块是可用的(已经下载到客户端),但没有执行该模块(还没有得到模块输出),可用于优化模块在模块集的位置
    • 语法:require.include(dependency: String)
    • 实例:

      // in file.js
      require.include("a");
      require.ensure(["a", "b"], function(require) {
        // Do something
      });
      require.ensure(["a", "c"], function(require) {
        // Do something
      });
      /* This results in:
         * entry chunk
           - file.js
           - a
         * anonymous chunk
           - b
         * anonymous chunk
           - c
      Without require.include "a" would be in both anonymous chunks.
      The runtime behavior isn‘t changed.
      */
    • 总结:略

其他API


配置详解

webpack命令提供了一系列的命令选项用于控制模块打包——可通过webpack --help查看这些选项。当需要配置较多的选项时,会使webpack命令变得非常臃肿,如:webpack --entry entry.js --output-path ./build --ouput-file bundle.js。所以webpack提供了一个配置对象来简化项目模块打包,在运行webpack命令的时候,只要指定这个配置对象即可——webpack --config webpack.config.jswebpack.config.js会输出配置对象,例如:

module.exports = {
    entry: "./entry.js,
    output: {
        path: "./build",
        filename: "bundle.js"
    }
};

观察上面的配置对象,可以发现配置对象本身就是一个模块,而不是JSON,我们可以在配置对象中随意的使用Javascript代码。除了在命令行界面中直接使用webpack,也可以在js代码中使用webpack api,例如:

var webpack = require("webpack");
webpack({
    entry: "./entry.js,
    output: {
        path: "./build",
        filename: "bundle.js"
}, callback);

webpack配置对象:

  • context
    webpack处理entry选项时的基础路径(绝对路径),默认值为process.cmd(),即webpack.config.js文件所在路径
  • entry:

    • 简介:webpack模块打包的入口,可以给entry赋字符串类型,数组类型和对象类型的值。
    • 可选值:
      • 字符串:字符串指定的模块在项目程序启动的时候加载
      • 字符串数组:字符串数组指定的所有模块被当做一个模块集,在项目程序启动的时候都会加载,数组最后一个元素作为模块集输出
      • 对象:webpack会打包多个模块集,对象的每个属性名作为模块集的名称,属性值可以是字符串和字符串数组。这个配置可用于实现非单页的程序,程序会有多个启动入口,具体实例可参考multiple entry points
    • 实例:

      {
          entry: {
              page1: "./page1",
              page2: ["./entry1", "./entry2"]
          },
          output: {
              // Make sure to use [name] or [id] in output.filename
              //  when using multiple entry points
              filename: "[name].bundle.js",
              chunkFilename: "[id].bundle.js"
          }
      }
  • output:option是个对象类型的值,option下的每个属性都可能会影响webpack模块打包结果。
  • module:用于配置模块加载插件,后面的章节再具体介绍
  • resolve
  • externals
  • target
  • bail
  • profile
  • cache
  • watch
  • watchOptions.aggregateTimeout
  • watchOptions.poll
  • debug
  • devtool
  • node
  • amd
  • loader
  • recordsPath, recordsInputPath, recordsOutputPath
  • plugins: 插件

注:不得不说webpack的强大,提供如此之多的配置选项,由于精力有限,后续再慢慢维护完善各个配置选项的说明。


加载器

加载器简介

加载器在webpack中作为资源(不只是javascript,包含其他静态资源)转换器,它本身是个可以运行在node.js环境中的函数。加载器根据参数对源文件进行处理,返回新的源文件,例如:在webpack中使用加载器处理CoffeeScrip和JSX——CoffeeScript是JavaScript的转译语言,JSX是Javascript的超集,都不能直接运行在浏览器中,但加载器会将他们编译成普通的javascript代码。

加载器的特性:

  • 加载器可以链接使用——多个加载器作用在一个资源上,按编写顺序使用加载器
  • 加载器可以是同步的,也可以是异步的?
  • 加载器运行在nodejs环境里,可以做node.js所能做的一切事情——开发自己的加载器时,可以体会到
  • 加载器可以接受参数,作为加载器的配置来影响加载器对资源的转换
  • 加载器可以通过npm来安装和发布——上面提到了加载器本身就是个运行在node.js环境的函数,所以可以作为node.js包发布在npm上
  • 加载器可以读取webpack的配置
  • 加载器可以结合webpakc的插件使用——插件在后面章节介绍

安装加载器

简介中提到了加载器是发布在npm上,作为一个模块使用——输出一个转换函数。所以我们可以通过npm来安装管理加载器,例如:
npm install xxx-loader --save-dev
或者
npm install xxx-loader --save
作为约定,加载器的命名通常为xxx-loader——xxx是加载器的名字,例如:json-loader。我们既可以使用xxx-loader来引用加载器,也可以直接使用xxx

加载器使用

在webpack中使用加载器有三种方式:
1. 直接在require中引用——不推荐
2. 在webpack.config.js中配置——推荐
3. 通过命令选项配置——不推荐

除了一些特殊情况在require中引用加载器外,我们推荐使用第二种方式来使用加载器——不需要解释,在后面的使用中很容易体会到。

下面简单介绍下这三种方式的用法:

  • require

    • 说明:可以在require语句(或者define,require.ensure等等)中指定加载器,加载器名称与模块名称通过!分割
    • 实例:

      require("./loader!./dir/file.txt");
      // => uses the file "loader.js" in the current directory to transform
      //    "file.txt" in the folder "dir".
      
      require("jade!./template.jade");
      // => uses the "jade-loader" (that is installed from npm to "node_modules")
      //    to transform the file "template.jade"
      
      require("!style!css!less!bootstrap/less/bootstrap.less");
      // => the file "bootstrap.less" in the folder "less" in the "bootstrap"
      //    module (that is installed from github to "node_modules") is
      //    transformed by the "less-loader". The result is transformed by the
      //    "css-loader" and then by the "style-loader".
    • 总结:第一个require使用了当前目录下的加载器./loader.js;第二个require使用了npm安装的加载器jade-loader;第三个加载器使用了加载器的链接特性,首先会使用less-loader处理源文件,处理后的源文件交给css-loader处理,最后交给style-loader——less-loader转换less源文件为普通的css文件,css-loader处理css文件中的url(由于webpack构建的代码会合并统一放在一个路径下,所以要处理下css引用的资源,否则在实际运行时,无法正确找到资源的位置),style-loader会处理css文件,通过js代码将插入到html页面中
  • 配置文件

    • 说明:学习require直接引用加载器后,我们发现很多资源使用的加载器是一样的。webpack提供了配置选项,让我们可以在配置文件中通过正则表达式来匹配资源,指定某一类资源要使用的加载器
    • 实例:

      {
          module: {
              loaders: [
                  { test: /\.jade$/, loader: "jade" },
                  // => "jade" loader is used for ".jade" files
      
                  { test: /\.css$/, loader: "style!css" },
                  // => "style" and "css" loader is used for ".css" files
                  // Alternative syntax:
                  { test: /\.css$/, loaders: ["style", "css"] },
              ]
          }
      }
  • 命令行选项
    webpack --module-bind jade --module-bind ‘css=style!css‘

加载器参数

加载器提供了一些参数来控制加载器对资源的转换,添加参数的方式类似于url链接中的查询参数。
- require
require("url-loader?mimetype=image/png!./file.png");
- 配置

`{ test: /\.png$/, loader: "url-loader?mimetype=image/png" }`

或者

```
{
    test: /\.png$/,
    loader: "url-loader",
    query: { mimetype: "image/png" }
}
```
  • 命令行选项
    webpack --module-bind "png=url-loader?mimetype=image/png"

加载器库

webpack有着丰富的加载器实习,可以参考list-of-loaders来查找你需要的加载器。

简单实例


插件

插件简介

webpack有丰富的插件接口,使得webpack变得更加灵活。webpack内部集成了一些插件,另外在npm上也有发布一些第三方的插件,当然你可以自己根据webpack的接口,开发属于自己的插件。

内建插件

webpack本身提供了一些插件供我们使用,如webpack.optimize.DedupePlugin——查找相等或近似的模块,避免在最终生成的文件中出现重复的模块。下面就以webpack.optimize.DedupePlugin为例展示webpack内部插件的使用:

  • webpack.config.js

    var webpack = require("webpack");
    var path = require("path");
    module.exports = {
        entry: "./example.js",
        output: {
            path: path.join(__dirname, "js"),
            filename: "output.js"
        },
        plugins: [
            new webpack.optimize.DedupePlugin()
        ]
    }
  • example.js

    var a = require("./a");
    var b = require("./b");
    a.x !== b.x;
    a.y !== b.y;
  • a/index.js

    module.exports = {
        x: require("./x"),
        y: require("./y"),
        z: require("../z")
    }
  • a/x.js
    module.exports = {"this is": "x"};
  • a/y.js
    module.exports = {"this is": "y", "but in": "a"};
  • b/index.js

    module.exports = {
        x: require("./x"),
        y: require("./y"),
        z: require("../z")
    }
  • b/x.js
    module.exports = {"this is": "x"};
  • b/y.js
    module.exports = {"this is": "y", "but in": "b"};
  • z.js
    module.exports = {"this is": "z"};
  • js/output.js
  • 总结
    观察上面的示例代码,a和b下都有模块x,且他们的代码是一样的。如果直接在命令行运行webpack example.js output.js,最终的生成文件会有两个模块x。再观察上面的webpack配置文件webpack.config.js,最后增加了plugins: [new webpack.optimize.DedupePlugin()],如果使用这个配置运行webpack构建,可以发现最后的生成文件js/ouput.js里只有个模块x,这个就是插件webpack.optimize.DedupePlugin的作用。

更多内建插件的使用请参考LIST OF PLUGINS

其他插件

除了内建插件外,还有一些webpack插件发布在npm上了,我们可以通过npm命令来安装,例如:
npm install --save-dev extract-text-webpack-plugin——extract-text-webpack-plugin是用于将某些类型的模块,如css,单独提取到文件的插件,具体如何使用该插件可以参考该项目的主页extract-text-webpack-plugin
如果想要查找更多的webpack插件,可以在npm上利用webpack-plugin关键字来搜索,即webpack-plugin

自定义插件

Plugins-api


开发工具

webpack-dev-server

认识webpack-dev-server

webpack-dev-server是一个轻量级的node.js服务器,同webpack,webpack-dev-server也可以分析模块的依赖关系进行打包——webpack命令的所有选项对webpack-dev-server命令都有效。但不同的是,webpack-dev-server不会在本地目录下生成目标文件,而是放在内存里,通过访问服务器相应地址获取。另外,webpack-dev-server自带有一个轻量级的runtime,浏览器可以通过Socket.IO与服务器连接,服务器向客户端浏览器送编译状态信息,然后客户端/浏览器根据这些信息做相应的处理,如:刷新,模块热替换等。

简单示例

  • 项目结构
    • app/
      • main.js
    • build/
    • test/
      • index.html
    • webpack.cong.js
  • webpack.config.js
module.exports = {
  entry: {
    app: ["./app/main.js"]
  },
  output: {
    path: "./build",
    publicPath: "/assets/",
    filename: "bundle.js"
  }
};
  • app/main.js
document.write("Hello World!")
  • test/index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <script src="assets/bundle.js"></script>
</body>
</html>
  • 命令行运行webpack-dev-server --content-base test/
    • 访问项目路径build发现并没有生成相应的构建文件
    • 浏览器访问localhost:8080/,观察运行结果
  • 分析总结
    • webpack-dev-server --content-base test/中的--content-base指定html等静态资源的位置
    • webpack.config.js中的output.publicPath指定webpack模块打包后在服务器的路径

webpack-dev-server命令行接口

所有的webpack命令选项对webpack-dev-server命令都有效,但是没有默认的output参数。除此之外,webpack-dev-server还有一些额外的选项:
- --content-base: 可以是文件、目录或者url,表示静态资源的基础路径
- --quiet: 布尔值,控制是否要在控制台输出所有信息
- --colors: 为控制台输出信息增加一些颜色
- --no-info: 禁止输出一些无聊的信息?
- --host: 主机名或ip地址
- –port: 端口号
- –inline: 布尔值,表示是否要将webpack-dev-server runtime集成到模块打包文件里,可以实现浏览器与服务器的通信
- --hot: 布尔值,表示增加HotModuleReplacementPlugin插件,且将服务器切换到热模式中。注意点:不要再额外添加HotModuleReplacementPlugin
- --https: 布尔值,表示webpack-dev-server是否开启HTTPS协议

webpack-dev-server API

http://webpack.github.io/docs/webpack-dev-server.html#api

最佳实战

在真实的项目开发中,前端需要与后台服务器交互——传输业务数据,这里通常会有一个后台服务器来向前端提供业务数据接口,我们也是在浏览器中访问这个后台服务器来使用功能的。这样的话,我们就需要将webpack生成的静态资源拷贝到我们项目的后台服务器下。如果是在最后发布的话,这样没有什么问题,但在实际开发中,每次调整代码都需要这么做,开发人员在就放弃使用webpack了。
当然,webpack已经为我们解决了这个问题,我们只需要同时运行后台服务器和webpack-dev-server——后台服务器的HTML页面包含指向webpack-dev-server静态资源的script标签,而webpack-dev-server只是充当前端静态资源的服务器。
示例:
- webpack.config.js

module.exports = {
  entry: {
    app: ["./app/main.js"]
  },
  output: {
    path: "./build",
    publicPath: "http://localhost:9090/",
    filename: "bundle.js"
  }
};
  • webpack-dev-server启动命令: webpack-dev-server --config webapck.config.js --host localhost --port 9090 --inline
  • 后台服务器的index.html包含: <script src="http://localhost:9090/bundle.js">
  • 假设后台服务器地址是http://localhost:8080,则在浏览器中访问: http://localhost:8080/index.html

注意点:
- 为了保证总是(为了非入口模块)向webpack-dev-server发送请求来获得静态资源,必须向output.publicPath提供一个完整的URL——如果只是个目录路径的话,非入口模块静态资源的请求会向后台服务器发送,而不是webpack-dev-server
- 为了连接webpacl-dev-server和它的runtime最好在webpack-dev-server命令后加上选项--inline

常见问题

  • webpack-dev-server的运行配置方式?
    • 命令行选项,参考 webpack-dev-server-cli ,此外webpack-dev-server在命令行里也可以使用webpack的配置选项来控制服务器构建
    • nodejs自定义脚本运行,参考api
    • webpack.config.js的 devServer选项,参考 devserver
    • 可参考实例 run-option-mode
  • webpack-dev-server的运行选项content-base与publicPath的区别?
    webpack-dev-server是一个 轻量级 服务器, content-base指定服务静态资源(html等)的路径。webpack-dev-server构建后的代码是放在内存里的,并通过publicPath指定的路径发布,如果没有指定的话在服务器地址的根路径下(如:假设host为127.0.0.1,port为8080,output.filename为bundle,则构建后的代码文件地址是 http://127.0.0.1:8080/bundle.js
  • hot模式与inline模式?

webpack-dev-middleware

webpack-dev-middleware

koa-webpack-dev

koa-webpack-dev


工具集成

  • grunt
  • gulp
  • bower
  • karma
  • Todo

源码分析

Todo


最佳实战

  • 模块划分
  • 优化
  • Todo

常见问题


参考文献

社区收藏

工具对比

中文文档

最佳实践

项目模板

Webpack + React

版权声明:本文为博主原创文章,未经博主允许不得转载。

webpack学习笔记

标签:webpack

原文地址:http://blog.csdn.net/zhbhun/article/details/47208885

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!