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

时间:2017-09-05 19:40:55

标签: javascript node.js webpack

我正在尝试了解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的实现!有人可以解释一下吗?

谢谢!

5 个答案:

答案 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 globalswebpack.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_ENVprocess.env.MY_VAR p 会更换,而process.envprocess 会保留其参考注入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和节点实例之间设置一个套接字来发送命令。从安全角度来看,这听起来像是一场噩梦,但可能有一些有效的用例。