博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
实用webpack插件之DefinePlugin
阅读量:6622 次
发布时间:2019-06-25

本文共 7218 字,大约阅读时间需要 24 分钟。

clipboard.png

通过阅读这篇文章,可以学习到如何使用DefinePlugin插件使得前端项目更加工程化,说清晰点就是如何使用这个插件,在编译阶段根据NODE_ENV自动切换配置文件,提升前端开发效率。

  • DefinePlugin的正确用法
  • 如何使用DefinePlugin添加配置文件,构建期间自动检测环境变化,也就是如何根据NODE_ENV引入配置文件?

DefinePlugin的正确用法

DefinePlugin中的每个键,是一个标识符或者通过.作为多个标识符。

  • 如果value是一个字符串,它将会被当做code片段
  • 如果value不是字符串,它将会被stringify(包括函数)
  • 如果value是一个对象,则所有key的定义方式相同。
  • 如果key有typeof前缀,它只是对typeof 调用定义的。

这些值将内联到代码中,压缩减少冗余。

new webpack.DefinePlugin({    PRODUCTION: JSON.stringify(true),    VERSION: JSON.stringify('5fa3b9'),    BROWSER_SUPPORTS_HTML5: true,    TWO: '1+1',    'typeof window': JSON.stringify('object'),    'process.env': {         NODE_ENV: JSON.stringify(process.env.NODE_ENV)     }});
console.log('Running App version' + VERSION);

plugin不是直接的文本值替换,它的值在字符串内部必须包括实际引用。典型的情况是用双引号或者JSON.stringify()进行引用,'"production"',JSON.stringify('production')。

重点:在vue-cli创建的项目中,凡是src下的文件,都可以访问到VERSION这个变量,例如main.js,App.vue等等

我们现在看一下上面的几种类型的key值,在代码中的输出。

console.log(PRODUCTION, VERSION, BROWSER_SUPPORTS_HTML5, TWO, typeof window, process.env);
PRODUCTION: true,VERSION: "5fa3b9",BROWSER_SUPPORTS_HTML5: true,TWO: 2,typeof window: "object",process.env: {NODE_ENV: "development"},

在代码中,我们一般会有以下几种用途:

  • 根据process.env.NODE_ENV区分环境
  • 引入配置文件
  • 根据NODE_ENV引入配置文件(这个很重要,后面会讲到)
Feature Flag

可以控制新特性和实验特性的开关。

new webpack.DefinePlugin({    'NICE_FEATURE': JSON.stringify(true),    'EXPERIMENTAL': JSON.stringify(false),})
process.env.NODE_ENV的正确配置方式是什么?
process: {    env: {        NODE_ENV: JSON.stringify('production')    }}

评价:非常不好,会overwrite整个process对象,仅仅保留新的NODE_ENV,破坏进程。

原始的process对象包含如下内容 ,包含了当前进程的很多信息。

process {  title: 'node',  version: 'v8.11.2',  moduleLoadList:    [ 'Binding contextify',],  versions:    { http_parser: '2.8.0'},  arch: 'x64',  platform: 'darwin',  release:    { name: 'node' },  argv: [ '/usr/local/bin/node' ],  execArgv: [],  env:    { TERM: 'xterm-256color'},  pid: 14027,  features:    { debug: false},  ppid: 14020,  execPath: '/usr/local/bin/node',  debugPort: 9229,  _startProfilerIdleNotifier: [Function: _startProfilerIdleNotifier],  _stopProfilerIdleNotifier: [Function: _stopProfilerIdleNotifier],  _getActiveRequests: [Function: _getActiveRequests],  _getActiveHandles: [Function: _getActiveHandles],  reallyExit: [Function: reallyExit],  abort: [Function: abort],  chdir: [Function: chdir],  cwd: [Function: cwd],  umask: [Function: umask],  getuid: [Function: getuid],  geteuid: [Function: geteuid],  setuid: [Function: setuid],  seteuid: [Function: seteuid],  setgid: [Function: setgid],  setegid: [Function: setegid],  getgid: [Function: getgid],  getegid: [Function: getegid],  getgroups: [Function: getgroups],  setgroups: [Function: setgroups],  initgroups: [Function: initgroups],  _kill: [Function: _kill],  _debugProcess: [Function: _debugProcess],  _debugPause: [Function: _debugPause],  _debugEnd: [Function: _debugEnd],  hrtime: [Function: hrtime],  cpuUsage: [Function: cpuUsage],  dlopen: [Function: dlopen],  uptime: [Function: uptime],  memoryUsage: [Function: memoryUsage],  binding: [Function: binding],  _linkedBinding: [Function: _linkedBinding],  _events:    { newListener: [Function],     removeListener: [Function],     warning: [Function],     SIGWINCH: [ [Function], [Function] ] },  _rawDebug: [Function],  _eventsCount: 4,  domain: [Getter/Setter],  _maxListeners: undefined,  _fatalException: [Function],  _exiting: false,  assert: [Function],  config: {},  emitWarning: [Function],  nextTick: [Function: nextTick],  _tickCallback: [Function: _tickDomainCallback],  _tickDomainCallback: [Function: _tickDomainCallback],  stdout: [Getter],  stderr: [Getter],  stdin: [Getter],  openStdin: [Function],  exit: [Function],  kill: [Function],  _immediateCallback: [Function: processImmediate],  argv0: 'node' }
'process.env': {    NODE_ENV: JSON.stringify('production')}

评价:不好,会overwrite整个process.env对象,破坏进程环境,导致破坏兼容性。

原始的process.env对象包含如下内容 ,包含了当前进程的很多信息。

{ TERM: 'xterm-256color',  SHELL: '/bin/bash',  TMPDIR: '/var/folders/lw/rl5nyyrn4lb0rrpspv4szc3c0000gn/T/',  Apple_PubSub_Socket_Render: '/private/tmp/com.apple.launchd.dEPuHtiDsx/Render',  USER: 'frank',  SSH_AUTH_SOCK: '/private/tmp/com.apple.launchd.MRVOOE7lpI/Listeners',  __CF_USER_TEXT_ENCODING: '0x1F5:0x19:0x34',  PATH: '/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Applications/Wireshark.app/Contents/MacOS',  PWD: '/Users/frank/Desktop/corporation/weidian-crm',  XPC_FLAGS: '0x0',  XPC_SERVICE_NAME: '0',  SHLVL: '1',  HOME: '/Users/frank',  LOGNAME: 'frank',  LC_CTYPE: 'zh_CN.UTF-8',  _: '/usr/local/bin/node' }
'process.env.NODE_ENV': JSON.stringify('production')

评价:好。因为仅仅对NODE_ENV值进行修改,不会破坏完整进程,也不会破坏兼容性。

如何使用DefinePlugin添加配置文件,构建期间自动检测环境变化,也就是如何根据NODE_ENV引入配置文件?

情景:开发阶段的接口地址往往与生产阶段的接口地址是不一致的。例如开发时是development.foo.com,而生产时是production.foo.com,如果需要打包发布,那么需要手动去替换域名或者是一个分支维护一个专门的配置文件,这两种方式是非常笨重的。

  • 手动替换

文件效率低下,每次在development和production见切换都需要进行配置文件的更新,容易出错

  • 配置文件

相对手动替换高级一些,但是不能一次性查看development和production的全部配置信息,需要在分支间切换,效率低下,且不适用于多种环境的配置

  • webpack.DefinePlugin()

全局配置文件,自动检测环境变化,效率高效。

webpack的DefinePlugin正是为我们解决这样一个问题,它维护一个全局的配置文件,在编译期间会自动检测process.env.NODE_ENV,根据当前的环境变量去替换我们的接口域名。

下面我将以一个实例来介绍如何正确使用webpack.DefinePlugin。

/config/api.js

const NODE_ENV = process.env.NODE_ENV;const config = {     production: {        FOO_API: 'production.foo.api.com',        BAR_API: 'production.bar.api.com',        BAZ_API: 'production.baz.api.com',     },     development: {        FOO_API: 'development.foo.api.com',        BAR_API: 'development.bar.api.com',        BAZ_API: 'development.baz.api.com',     },     test: {        FOO_API: 'test.foo.api.com',        BAR_API: 'test.bar.api.com',        BAZ_API: 'test.baz.api.com',     }}module.exports = config[NODE_ENV];

webpack.dev.conf.js/webpack.prod.conf.js/webpack.test.conf.js

const apiConfig = require('./config/api');const webpackConfig = {    plugins: [        new webpack.DefinePlugin({            API_CONFIG: JSON.stringify(apiConfig);        })    ]}...

custom.component.vue

上述仅仅适用于vue-cli2.0时代,vue-cli3.0引入了webpack-chain,配置方式大大不同,下文将给出示例。

如何在vue.config.js中,使用使用DefinePlugin添加配置文件,构建期间自动检测环境变化,也就是如何根据NODE_ENV引入配置文件?

vue.config.js

const apiConfig = require('./config/api');module.exports = {    chainWebpack: config => {        config            .plugin('define')            .tap(args => {                 args[0].API_CONFIG = JSON.stringify(apiConfig)                return args            })    }}

需要注意的是,在vue-cli3.0中,我们不能直接SET NODE_ENV=production或者EXPORT NODE_ENV=production。

因为vue-cli-servive有3种模式,serve默认为development,build为production,若想修改vue-cli-service包中的NODE_ENV,需要通过vue-cli-service serve --mode production进行切换。
就像下面这样:

{  "scripts": {    "dev": "vue-cli-service serve", // mode默认为development     "production": "vue-cli-service serve --mode production",   },}

注意:我们只能在development, production或者test 3个模式下进行切换,不能引入类似preproduction之类的自定义node环境,但是实际上这3个环境已经足以满足大多数的开发情况。

为什么vue-cli 3.0中的DefinePlugin可以用config.plugin('define')修改入参?

在中,有下面的代码:

webpackConfig      .plugin('define')        .use(require('webpack/lib/DefinePlugin'), [          resolveClientEnv(options)        ])

这一点很关键!我们在vue.config.js中拿到的config.plugin('define'),实际上时vue-service内部创建的webpack.DefinePlugin实例的引用 !

明确了这一点,我们在以后增强webpack默认插件配置时,需要先到vue-service的源码中寻找一番,看看有没有对应plugin的引用,若有,必须根据vue-service定义的名字直接引用,否则会修改失败。

转载地址:http://pajpo.baihongyu.com/

你可能感兴趣的文章
HttpRunnerManager安装部署
查看>>
在网页中使用H1标记的须注意的事项
查看>>
JQ绑定事件的叠加和解决,index()方法的坑
查看>>
关于不定项参数的查询方法(多条件查询)
查看>>
[百度杯-二月场](Misc-Web)爆破-1
查看>>
构建之法阅读笔记
查看>>
HttpServer - Web服务器模型
查看>>
edm表格布局中一些标签必须写的一些属性值
查看>>
【VMCloud云平台】SCO(八)SCO结合SCOM
查看>>
RabbitMQ实例教程:用Java搞定工作队列
查看>>
安全管理平台未来的发展趋势【提要】
查看>>
Lync Server外部访问系列PART2:部署边缘
查看>>
为什么很多人努力了却死一地
查看>>
统一沟通-技巧-8-在internet上是否正常-1-For Exchange Server 2010
查看>>
一个不错的Cocos 1.6动画编辑器入门教程
查看>>
nagios监控三部曲之——nagios实现飞信报警(3)
查看>>
【COCOS2DX-LUA 脚本开发之十一】C/C++与Lua之间进行数据函数交互
查看>>
ISO27000系列标准
查看>>
CCID: 2012-2013年度中国信息安全产品市场研究年度报告
查看>>
智能化连接厨房——海尔馨厨冰箱初体验印象
查看>>