webpack多页应用架构系列(二):webpack配置经常使用部分有哪些?

本文首发于 Array_Huang的技术博客—— 实用至上,非经做者赞成,请勿转载。
原文地址: http://www.javashuo.com/article/p-eihwhadk-kg.html
若是您对本系列文章感兴趣,欢迎关注订阅这里: https://segmentfault.com/blog/array_huang

前言

webpack的配置文件是一个node.js的module,用CommonJS风格来书写,形如:javascript

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

webpack的配置文件并无固定的命名,也没有固定的路径要求,若是你直接用webpack来执行编译,那么webpack默认读取的将是当前目录下的webpack.config.jscss

$ pwd
/d/xampp/htdocs/webpack-seed
$ webpack # webpack此时读取的其实是/d/xampp/htdocs/webpack-seed/webpack.config.js

若是你有其它命名的须要或是你有多份配置文件,可使用--config参数传入路径:html

$ webpack --config ./webpackConfig/dev.config.js

另外,在CLI执行webpack指令时可传入的参数(固然除了--config)实际上均可以在配置文件里面直接声明,我强烈建议能够的话尽可能都在配置文件里写好,有须要的话写两份配置也好三份也好(反正配置文件间也是能够互相引用的,相同的部分就拆成一个module出来以供读取,最后拼成各类状况下须要的配置就行了)。前端

入口文件配置:entry参数

entry能够是字符串(单入口),能够是数组(多入口),但为了后续发展,请务必使用object,由于object中的key在webpack里至关于此入口的name,既能够后续用来拼生成文件的路径,也能够用来做为此入口的惟一标识。
我推荐的形式是这样的:java

entry: { // pagesDir是前面准备好的入口文件集合目录的路径
  'alert/index': path.resolve(pagesDir, `./alert/index/page`), 
  'index/login': path.resolve(pagesDir, `./index/login/page`), 
  'index/index': path.resolve(pagesDir, `./index/index/page`),
},

对照个人脚手架项目webpack-seed的文件目录结构,就很清楚了:node

├─src # 当前项目的源码
    ├─pages # 各个页面独有的部分,如入口文件、只有该页面使用到的css、模板文件等
    │  ├─alert # 业务模块
    │  │  └─index # 具体页面
    │  ├─index # 业务模块
    │  │  ├─index # 具体页面
    │  │  └─login # 具体页面

因为每个入口文件都至关于entry里的一项,所以这样一项一项地来写实在是有点繁琐,我就稍微写了点代码来拼接这entry:webpack

var pageArr = [
    'index/login',
    'index/index',
    'alert/index',
  ];
  var configEntry = {};
  pageArr.forEach((page) => {
    configEntry[page] = path.resolve(pagesDir, page + '/page');
  });

输出文件:output参数

output参数告诉webpack以什么方式来生成/输出文件,值得注意的是,与entry不一样,output至关于一套规则,全部的入口都必须使用这一套规则,不能针对某一个特定的入口来制定output规则。output参数里有这几个子参数是比较经常使用的:path、publicPath、filename、chunkFilename,这里先给个webpack-seed中的示例:git

output: {
      path: buildDir, // var buildDir = path.resolve(__dirname, './build');
      publicPath: '../../../../build/',
      filename: '[name]/entry.js',    // [name]表示entry每一项中的key,用以批量指定生成后文件的名称
      chunkFilename: '[id].bundle.js',
    },

path

path参数表示生成文件的根目录,须要传入一个绝对路径。path参数和后面的filename参数共同组成入口文件的完整路径。github

publicPath

publicPath参数表示的是一个URL路径(指向生成文件的根目录),用于生成css/js/图片/字体文件等资源的路径,以确保网页能正确地加载到这些资源。
publicPath参数跟path参数的区别是:path参数实际上是针对本地文件系统的,而publicPath则针对的是浏览器;所以,publicPath既能够是一个相对路径,如示例中的'../../../../build/',也能够是一个绝对路径如http://www.xxxxx.com/。通常来讲,我仍是更推荐相对路径的写法,这样的话总体迁移起来很是方便。那何时用绝对路径呢?其实也很简单,当你的html文件跟其它资源放在不一样的域名下的时候,就应该用绝对路径了,这种状况很是多见于后端渲染模板的场景。web

filename

filename属性表示的是如何命名生成出来的入口文件,规则有如下三种:

  • [name],指代入口文件的name,也就是上面提到的entry参数的key,所以,咱们能够在name里利用/,便可达到控制文件目录结构的效果。
  • [hash],指代本次编译的一个hash版本,值得注意的是,只要是在同一次编译过程当中生成的文件,这个[hash]的值就是同样的;在缓存的层面来讲,至关于一次全量的替换。
  • [chunkhash],指代的是当前chunk的一个hash版本,也就是说,在同一次编译中,每个chunk的hash都是不同的;而在两次编译中,若是某个chunk根本没有发生变化,那么该chunk的hash也就不会发生变化。这在缓存的层面上来讲,就是把缓存的粒度精细到具体某个chunk,只要chunk不变,该chunk的浏览器缓存就能够继续使用。

下面来讲说如何利用filename参数和path参数来设计入口文件的目录结构,如示例中的path: buildDir, // var buildDir = path.resolve(__dirname, './build');filename: '[name]/entry.js',那么对于key为'index/login'的入口文件,生成出来的路径就是build/index/login/entry.js了,怎么样,是否是很简单呢?

chunkFilename

chunkFilename参数与filename参数相似,都是用来定义生成文件的命名方式的,只不过,chunkFilename参数指定的是除入口文件外的chunk(这些chunk一般是因为webpack对代码的优化所造成的,好比因应实际运行的状况来异步加载)的命名。

各类Loader配置:module参数

webpack的核心实际上也只能针对js进行打包,那webpack一直号称可以打包任何资源是怎么一回事呢?原来,webpack拥有一个相似于插件的机制,名为Loader,经过Loader,webpack可以针对每一种特定的资源作出相应的处理。Loader的种类至关多,有些比较基础的是官方本身开发,而其它则是由webpack社区开源贡献出来的,这里是Loader的List:list of loaders
而module正是配置什么资源使用哪一个Loader的参数(由于就算是同一种资源,也可能有不一样的Loader可使用,固然不一样Loader处理的手段不同,最后结果也天然就不同了)。module参数有几个子参数,可是最经常使用的天然仍是loaders子参数,这里也仅对loaders子参数进行介绍。

loaders参数

loaders参数又有几个子参数,先给出一个官方示例:

module.loaders: [
  {
    // "test" is commonly used to match the file extension
    test: /\.jsx$/,

    // "include" is commonly used to match the directories
    include: [
      path.resolve(__dirname, "app/src"),
      path.resolve(__dirname, "app/test")
    ],

    // "exclude" should be used to exclude exceptions
    // try to prefer "include" when possible

    // the "loader"
    loader: "babel-loader"
  }
]

下面一一对这些子参数进行说明:

  • test参数用来指示当前配置项针对哪些资源,该值应是一个条件值(condition)。
  • exclude参数用来剔除掉须要忽略的资源,该值应是一个条件值(condition)。
  • include参数用来表示本loader配置仅针对哪些目录/文件,该值应是一个条件值(condition)。这个参数跟test参数的效果是同样的(官方文档也是这么写的),我也不明白为嘛有俩一样规则的参数,不过咱们姑且能够本身来划分这二者的用途:test参数用来指示文件名(包括文件后缀),而include参数则用来指示目录;注意同时使用这二者的时候,其实是and的关系。
  • loader/loaders参数,用来指示用哪一个/哪些loader来处理目标资源,这俩货表达的实际上是一个意思,只是写法不同,我我的推荐用loader写成一行,多个loader间使用!分割,这种形式相似于管道的概念,又或者说是函数式编程。形如loader: 'css?!postcss!less',能够很明显地看出,目标资源先经less-loader处理事后将结果交给postcss-loader做进一步处理,而后最后再交给css-loader。

条件值(condition)能够是一个字符串(某个资源的文件系统绝对路径),能够是一个函数(官方文档里是有这么写,但既没有示例也没有说明,我也是醉了),能够是一个正则表达式(用来匹配资源的路径,最经常使用,强烈推荐!),最后,还能够是一个数组,数组的元素能够为上述三种类型,元素之间为与关系(既必须同时知足数组里的全部条件)。须要注意的是,loader是能够接受参数的,方式相似于URL参数,形如'css?minimize&-autoprefixer',具体每一个loader接受什么参数请参考loader自己的文档(通常也就只能在github里看了)。

添加额外功能:plugins参数

这plugins参数至关于一个插槽位(类型是数组),你能够先按某个plugin要求的方式初始化好了之后,把初始化后的实例丢到这里来。

示例代码

诸位看本系列文章,搭配我在Github上的脚手架项目食用更佳哦(笑):Array-Huang/webpack-seed(https://github.com/Array-Huang/webpack-seed)
本文提到的全部内容,均可以在示例代码根目录下的webpack.config.js里找到对应的内容(不过可能稍微有点复杂呢,毕竟是一个能够投入生产环境的架构了,不过看过我后续的文章,就会以为很简单的啦哈哈哈哈)。

附系列文章目录(同步更新)

本文首发于 Array_Huang的技术博客—— 实用至上,非经做者赞成,请勿转载。
原文地址: http://www.javashuo.com/article/p-eihwhadk-kg.html
若是您对本系列文章感兴趣,欢迎关注订阅这里: https://segmentfault.com/blog/array_huang
相关文章
相关标签/搜索