节点进程对象可用于浏览器客户端代码

我想了解webpack如何使用DefinePlugin。 我有:

new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify('development'), }), 

和一个function:

 export const foo = () => { console.log(process) console.log(process.env.NODE_ENV) } window.foo = foo 

当我打印foo时,我在浏览器控制台中看到以下内容:

 ƒ foo() { console.log(process); console.log("development"); } 

当webpack编译input文件时,好像variables“development”被注入了。 同时webpack也将过程对象注入到JavaScript代码中,当foo被调用时,浏览器打印出过程对象:

 {title: "browser", browser: true, env: {…}, argv: Array(0), nextTick: ƒ, …} 

我的问题是,怎样才能使浏览器可以使用作为Node概念的进程对象?

其实如果我这样做:

 window.process = process 

我可以在浏览器控制台中使用process.nextTick! 我以为nextTick函数是一个特定于Node的实现! 有人可以解释吗?

谢谢!

正如在这里提到的https://webpack.js.org/configuration/node/#node-process,webpack可以为不同的节点function做polyfills,但是它看起来像node.process是一个"mock"

“模拟”:提供一个模拟实现预期的接口,但很less或没有function。

你有没有testing过,看它是否真的有效? 它可能只是一个空壳。

如果有效,我假设这个插件实际上使用了类似于这个博客文章中所示的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

希望你find这个答案有所帮助。

底线是我相信这是一个来自某个地方的polyfill。

我假设你正在本地的webpack dev服务器上进行实验,而不是在你的生产版本中。 Webpack dev服务器利用websockets在底层节点进程和前端bundle之间进行实时通信。 如果你想在生产环境中使用它,你将需要在你的前端JS和你的节点实例之间build立一个套接字来发送命令。 从安全angular度来看,这听起来像一场噩梦,但可能有一些有效的用例。

webpack如何处理Node全局variables和webpack.DefinePlugin实际上是两个不同的问题。

默认节点全局variables全局注入的 ,而webpack.DefinePlugin中定义的常量在所有代码库中被逐个replace

例如:

 // 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_ENVprocess.env.MY_VAR 实际上被replace ,而process.envprocess 保持它们对注入process 模拟 的引用

但是webpack.DefinePlugin也可以覆盖 webpack.DefinePlugin process对象 (或者只是其中的一部分):这意味着获取意外行为的风险很大。

从Webpack文档 :

当定义stream程偏好的值'process.env.NODE_ENV':JSON.stringify('production')over process:{env:{NODE_ENV:JSON.stringify('production')}}。 使用后者将覆盖过程对象,该过程对象可能会破坏某些需要定义过程对象的其他值的模块的兼容性。

例如:

 // 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', "development"); // compiled console.log('process', "override"); console.log('process.env', "override".env); // [boum!] console.log('process.env.NODE_ENV', "development"); // [replaced by DefinePlugin!]