我正在尝试了解webpack如何使用DefinePlugin。我有:
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('development'),
}),
和一个功能:
export const foo = () => {
console.log(process)
console.log(process.env.NODE_ENV)
}
window.foo = foo
当我打印foo时,我在浏览器控制台中看到以下内容:
ƒ foo() {
console.log(process);
console.log("development");
}
似乎在webpack编译输入文件时注入了变量“development”。同时webpack还将进程对象注入到JavaScript代码中,浏览器确实在调用foo时打印出进程对象:
{title: "browser", browser: true, env: {…}, argv: Array(0), nextTick: ƒ, …}
我的问题是,如何将流程对象(即Node概念)提供给浏览器?
事实上,如果我这样做:
window.process = process
我可以在浏览器控制台内使用process.nextTick!我认为nextTick函数是一个特定于Node的实现!有人可以解释一下吗?
谢谢!
答案 0 :(得分:2)
如此处https://webpack.js.org/configuration/node/#node-process所述,webpack可以为不同的节点功能制作polyfill,但它显示为node.process
是"mock"
;
“mock”:提供一个实现预期接口但很少或没有功能的模拟器。
您是否测试过它以确定它是否真的有效?它可能只是一个空壳。
如果有效,我认为该插件实际上使用了node-process之类的内容,如此博客帖子所示:http://timnew.me/blog/2014/06/23/process-nexttick-implementation-in-browser/
从该博文中复制:
process.nextTick = (function () {
var canSetImmediate = typeof window !== 'undefined'
&& window.setImmediate;
var canPost = typeof window !== 'undefined'
&& window.postMessage && window.addEventListener;
if (canSetImmediate) {
return function (f) { return window.setImmediate(f) };
}
if (canPost) {
var queue = [];
window.addEventListener('message', function (ev) {
var source = ev.source;
if ((source === window || source === null) && ev.data === 'process-tick') {
ev.stopPropagation();
if (queue.length > 0) {
var fn = queue.shift();
fn();
}
}
}, true);
return function nextTick(fn) {
queue.push(fn);
window.postMessage('process-tick', '*');
};
}
return function nextTick(fn) {
setTimeout(fn, 0);
};
})();
根据您提供的信息确定有点难。如果它确实有效,我认为您很可能在节点应用中启用了Browserify。也许你在这里找到了一些你需要的东西:https://webpack.js.org/loaders/transform-loader/#src/components/Sidebar/Sidebar.jsx
希望你觉得这个答案有点帮助。
最重要的是,我相信它是来自某个地方的polyfill。
答案 1 :(得分:2)
webpack如何处理Node globals和webpack.DefinePlugin
实际上是两个不同的问题。
默认节点全局 全局注入,而webpack.DefinePlugin
中定义的常量在物理上逐个替换< / strong>通过所有代码库。
例如:
// config
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('development'),
'process.env.MY_VAR': {foo: JSON.stringify('bar')},
}),
// source
console.log('process.env.NODE_ENV', process.env.NODE_ENV);
console.log('process.env.MY_VAR', process.env.MY_VAR);
console.log('process.env', process.env);
console.log('process', process);
// compiled
console.log('process.env.NODE_ENV', "development");
console.log('process.env.MY_VAR', __webpack_require__.i({"foo":"bar"}));
console.log('process.env', process.env);
console.log('process', process);
请注意,process.env.NODE_ENV
和process.env.MY_VAR
p 会更换,而process.env
和process
会保留其参考注入process
模拟。
但webpack.DefinePlugin
也可以覆盖模拟的process
对象(或只是其中的一部分):强大的力量意味着获得的风险意外行为。
来自Webpack docs:
为流程首选定义值&quot; process.env.NODE_ENV&#39;:JSON.stringify(&#39; production&#39;)over process:{env:{NODE_ENV:JSON.stringify(&# 39;生产&#39;}}}。使用后者将覆盖进程对象,这可能会破坏与某些模块的兼容性,这些模块期望定义进程对象上的其他值。
例如:
// config
new webpack.DefinePlugin({
'process': JSON.stringify('override'),
'process.env.NODE_ENV': JSON.stringify('development'),
}),
// source
console.log('process', process);
console.log('process.env', process.env);
console.log('process.env.NODE_ENV', process.env.NODE_ENV);
// compiled
console.log('process', "override");
console.log('process.env', "override".env); // [boum!]
console.log('process.env.NODE_ENV', "development"); // [replaced by DefinePlugin!]
答案 2 :(得分:0)
这不能直接回答这个问题,但这是我需要的解决方案。我试图访问webpack编译的代码中的process
,打算将编译后的代码在NodeJS环境中而不是在浏览器中运行。 process
变量在window
上不存在,但是在global
上。
解决方案是在webpack配置中设置target
。
webpack.config.js
const config = {
// ...
target: 'node',
// ...
};
module.exports = config;
这将删除window
模拟。
答案 3 :(得分:0)
请参阅 https://webpack.js.org/configuration/node/#node
这些选项配置是要填充还是模拟某些Node.js全局变量和模块。这使最初为Node.js环境编写的代码可以在其他环境(例如浏览器)中运行。
此功能由webpack的内部NodeStuffPlugin插件提供。如果目标是“ web”(默认)或“ webworker”,则NodeSourcePlugin插件也会被激活。
答案 4 :(得分:-1)
我将假设您正在本地webpack开发服务器上进行实验,而不是在生产版本中进行实验。 Webpack dev服务器利用websockets在底层节点进程和前端bundle之间进行实时通信。如果要在生产环境中使用它,则需要在前端JS和节点实例之间设置一个套接字来发送命令。从安全角度来看,这听起来像是一场噩梦,但可能有一些有效的用例。