首页 > 其他分享 >实用webpack插件之DefinePlugin

实用webpack插件之DefinePlugin

时间:2022-10-07 23:03:37浏览次数:60  
标签:Function NODE 插件 vue webpack production ENV DefinePlugin API

通过阅读这篇文章,可以学习到如何使用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

<template>
...
</template>
<script>// 这里也可以访问到API_CONFIG
export default {
// 这里无论是data函数,methods对象,computed对象,watch对象,都可以访问到API_CONFIG;
data() {
return {
fooApi: API_CONFIG.FOO_API,
user:{
id: '',
name: '',
},
hash: '',
}
},
computed: {
userAvator() {
return `${API_CONFIG.BAR_API}?id=${user.id}&name=${user.name}`
}
},
methods: {
uploadImage() {
api.uploadImage({user: `${API_CONFIG.BAZ}\${hash}`})
.then(()=>{})
.catch(()=>{})
}
}
}
</script>

上述仅仅适用于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

需要注意的是,在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')修改入参?

在​​源码文件base.js​​中,有下面的代码:

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定义的名字直接引用,否则会修改失败。

  • 微信公众号: 大大大前端

标签:Function,NODE,插件,vue,webpack,production,ENV,DefinePlugin,API
From: https://blog.51cto.com/u_15725382/5735203

相关文章

  • Skywalking光会用可不行,必须的源码分析分析 - Skywalking Agent &插件解析
    3Skywalking源码导入接上文,已经学习了Skywalking的应用,接下来我们将剖析Skywalking源码,深度学习SkywalkingAgent。3.1源码环境搭建当前最新版本是8.3.0,我们首先找到8.3.......
  • k8s中kibana集成ldap和安装饼图插件
    集成ldap和添加饼图插件都需要重启容器1、创建configmapapiVersion:v1kind:ConfigMapmetadata:name:ldap-confignamespace:monitoringdata:ldap.toml:|......
  • 使用 PostCSS 插件让你的网站支持暗黑模式
    最近公司需要给多个webapp(大概20+)加上多皮肤的功能,原先默认是白色皮肤,我们先从暗黑模式入手,从而逐渐实现多皮肤功能。本篇记录下实现思路。换肤方案cssvariablescssvaria......
  • 一起来写 VS Code 插件:实现一个翻译插件
    前言上一篇介绍了用​​codesnippets​​​的方式开发一个插件,本文将通过实现一个翻译插件实例的方式来熟悉VSCode插件开发的常见功能和方法。当然大家可以前往VSCo......
  • [参考]2022 IDA插件大赛结果
    2022IDA插件大赛结果Hexray原文地址:2022Plug-InContest(hex-rays.com),本文主要对插件进行转载。Wereceived9interestingsubmissionsthisyear!Asusual,many......
  • 传奇龙族引擎三端插件使用说明
    ​1.解压龙族三端工具包,打开里面的插件文件夹将插件放到游戏版本Mir200里面把插件**“MultiEndEngine.dll”和“MultiEndEngine.Jdk”**复制到你的游戏版本MirServer......
  • C4D 2023插件:Arnold for mac(C4D S2023阿诺德渲染器)
     Arnold是一款先进的蒙特卡洛光线追踪渲染器,专为动画长度和视觉效果的需求而打造。C4DtoA4.4.0使用Arnold7.1.3.1 ,是一个功能版本,带来了对Cinema4D2023中OCI......
  • webpack5简单配置
    webpack4之后webpack5又做了蛮多的变化,这里简单介绍一下webpack5的配置可以参考官网mkdirreact-clicdreact-clinpminit初始化package.jsonnpminstallwebpack......
  • [转] webpack 插件的作用
      我们需要先安装插件:npmiwebpack-dev-server-D然后修改 package.json文件:"scripts":{"dev":"webpackserve"}, ......
  • Visual Studio Code +PHP开发 推荐插件
    1、PHPIntelephense:超好用php智能代码提示器,支付代码提示、查找定义、类搜索等功能,非常强大2、PHP接口注释插件:安装好后可以使用“/**”快捷键+Tab自动生成接......