设置模块索引目录

在 webpack 中,主要提供aliasmodules来进行索引目录的设置。

  • alias:设置导入路径的简便写法。如果你有大量的文件依赖路径非常长的话,除了使用 modules设置参考路径之外,还可以根据alias来设置路径映射的 key。另外,它还提供了$来进行文件的精确匹配,这个看看文档就行,感觉不常用。例如:
alias: {
  Villainhr: path.resolve(__dirname, 'src/Villainhr/')
}

# 如果要获取 src/Villainhr/index.js 的话,可以直接在 import 写入:

import test from 'Villainhr/index';

modules: 用来设置模块解析的目录。这样,在进行模块查找的时候,webpack 会优先遍历你定义的目录。如果,你还有自定义模块在,通过普通模块解析是找不到的,这时候可以直接在modules中添加 src。

modules: [path.resolve(__dirname, "src"), "node_modules"]

package.json 索引解析

和模块搜索最关键的文件是package.json、在 node 环境下,如果模块文件中存在 package.json,会根据其main字段定义的文件来进行索引。通过 webpack 设定的模块索引,可以更灵活的设置查找规则。其中,主要依赖的是mainFieldsmainFilesextensions这三个字段。

  • mainFields[Array]: 接受的是数组,用来设置在 package.json 文件中,用来定义具体查找文件的字段。例如: mainFields: ["browser", "module", "main"],则会按顺序搜索:browsermodulemain这三个字段。
  • mainFiles[Array]:如果文件不含有 package.json,则直接根据mainFiles定义的文件来索引。
  • extensions[Array]:设置默认文件后缀名。当索引文件时,如果具体路径没带文件名的话,会根据exntensions定义的内容来获取。

loader 简便书写

modules指令下,添加具体调用的loader一定需要带上后面的-loader尾缀。如果你不想带,则会默认报错。不想报错的话,可以使用moduleExtensions指令来说明:

moduleExtensions: ['-loader']

这样,就可以直接在 module 中直接不带-loader引用:

loader: 'eslint'

externals 定义外部依赖

externals 是用来排除某些你并不想打包的库,并且可以通过import/require在全局环境中调用。这个选项一般是提供给一些开源库或者组件作者使用的。

相当于,你调用了一个库,而最终实际打包的文件里面剔除该库的存在,只是留下了一个引用接口。

// 剔除 sw-router 库
externals: {
  Router: 'sw-router'
}

// 在代码中使用
import Router from 'Router';

它可以接收如下类型:(array object function regex)

  • array:用来过滤打包文件中的子模块。

  • // 将 ./math 文件中的 subtract 过滤不打包。
    externals: {
      subtract: ['./math', 'subtract']
    }
    
    // 忽略如下文件打包:
    import {subtract} from './math';
    
  • object:通过 key 值,来决定在不同模块规范下,文件暴露的接口名。其中,commonjs 代表 require 模块规则,amd 则代表 define 模块规则,root 则是代表该模块在全局环境,例如 window 访问的对象名。
externals : {
  ex_loadsh : {
    commonjs: "lodash", // require('loadsh')
    amd: "lodash",  // define(['loadsh'])
    root: "_" // window._
  }
}

通过 externals 定义之后,我们在不同环境访问 loadsh 的方式就变为:

// 全局环境
window.ex_loadsh;

// 模块包中
require('ex_loadsh');
  • function: 前面几个写法都是将需要提出的文件写死,而 function 提供了可以灵活配置的 external list。比如,你想剔除所有 node_modules 包中的库,而里面又有几个包需要引用的话,可以写为:
externals: [
  function(context, request, callback) {
    if (/^yourregex$/.test(request)){ // 剔除具体的包
      return callback(null, 'amd ' + request);  // 通过 amd 定义剔除文件的引用方式
    }
    callback(); 
  }
]

不过,更方便的直接使用webpack-node-externals来完成。如果项目不是特别复杂,这个配置选项一般用不上。

  • regexp: 使用正则选项,相当于就是通过正则的test方法,通过路径名的检查,来决定是否剔除。
externals: /^(jquery|\$)$/i; //剔除 jquery 和 $ 文件导入

# 剔除如下文件
import $ from 'jquery';
// or
import $ from '$';

target 设定打包环境

这里,如果项目并不复杂的话,可以直接忽略该属性设置

因为 webpack 本身都是多环境应用,你可以在 node、web、webworker 甚至其他跨平台环境中:node-webkit、electron-main。其常用选项有三个:

  • node:在后台环境中使用
  • web:在浏览器主线程环境中使用
  • webworker:在 web-worker 环境中使用

具体设置方式为:

{
  target: 'node'
}

不过,该选项常常用于复杂的打包项目中。比如,一个项目你需要同时输出在 web 环境中和在 webworker 环境中运行的打包脚本文件。这时候,就涉及到多入口文件的 webpack.config.js 设置。这里,可以利用webpack-merge来帮助我们完成多入口的合并设置。

var baseConfig = {  
  target: 'async-node',
  entry: {
    entry: './entry.js'
  },
  output: {
    filename: '[name].js',
    path: path.resolve(__dirname, './dist')
  }
};

let targets = ['web', 'webworker', 'node', 'async-node', 'node-webkit', 'electron-main'].map((target) => {
  let base = webpackMerge(baseConfig, {
    target: target,
    output: {
      path: path.resolve(__dirname, './dist/' + target),
      filename: '[name].' + target + '.js'
    }
  });
  return base;
});

module.exports = targets;

在导出的就会同时编译出 web、webworker、node 等目录,里面的文件就是对应环境中使用的包。如果想用原生的可以直接导出,数组形式的配置项:

var path = require('path');
var serverConfig = {
  target: 'node',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'lib.node.js'
  }
};

var clientConfig = {
  target: 'web', // <=== can be omitted as default is 'web'
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'lib.js'
  }
};

module.exports = [ serverConfig, clientConfig ];

通过,在 webpack 主文件中,具体设置需要使用的配置,即可完成指定环境的编译操作。

node 提供模拟包

node 指令主要是让 webpack 将在 node 环境运行的包,提供相关的设置,能够直接在打包文件中访问。其策略可以是提供一个桩(空对象),或者直接将现成的包直接打进去。

其基本可选择的值主要是直接参考 node 的模块包名:

console
global
process
__filename
__dirname
Buffer
setImmediate

不过,主要用到的还是 Buffer 和 global 两个配置项。其打包策略选项有 4 个值:

  • true: 直接将该包的 polyfill 直接打进去
  • “mock”: 提供空接口。可以访问对应的接口名,但是没有任何作用。
  • “empty”: 提供一个空对象。这个连接口名都不能访问
  • false: 啥都没有。

上述默认配置值为:

node: {
  console: false,
  global: true,
  process: true,
  __filename: "mock",
  __dirname: "mock",
  Buffer: true,
  setImmediate: true
}

这样设置了之后,我们可以直接在主文件入口中访问:

const Buffer = require('Buffer');

// doSth()

如果你想啥都不提供,最好直接将node设置为false

node:false

devtool 开启 sourceMap 选项

devtool 主要是给 JS 文件添加对一个的 sourceMap 文件。不过,webpack 可以生成多种 sourceMap 文件,具体的区别是,映射还原度的区别。这里直接参考 webpack 官方文档即可。

其中,最常用的选项就是source-mapcheap-eval-source-map。(这里实在太多了,各位看着选个合适的就行)如果你想关闭,sourceMap 的话,可以直接使用hidden-source-map,或者不传。比如,下面的配置:

if (COMPILE) {
    config.devtool = 'hidden-source-map';
    config.output.path = path.join(__dirname,'public');
}

devServer 本地 localhost 调试

devServer 是 webpack 提供一个简便的调试服务。它可以根据字段配置,自动起一个 server 来进行调试。如果用过webpack-dev-server的同学,应该就很熟悉了。那如果利用 webpack,起一个简单的 server 服务呢?这里,直接给一份配置即可:

devServer: {
  contentBase: path.join(__dirname, "dist"), // 设置静态资源访问路径
  compress: true, // 执行压缩
  port: 9000 // 监听的端口
}

不过,更常用的是利用 webpack server 的热更新机制。配置列表为:

devServer: {
  contentBase: path.join(__dirname, "dist"),
  compress: true,
  port: 9000,
  hot: true,
  hotOnly: true
}

接着,你就可以通过localhost:9000来访问你编译过后的目录。

剩下 server 配置,大家可以直接参考webpack devServer

最后说几句

到这里,webpack 3.x 的整个内容差不多已经阐述完了。不过,关于 plugin 的内容,我们这里并没有过多提及,因为,对于一般 webpack 纯使用者来说,直接使用现有成熟的 plugin 即可。还有一个原因是,webpack plugin 内容真的有点多,这里篇幅有限就不写了。后面专门针对其内容详述一篇。

results matching ""

    No results matching ""