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

pla*_*pus 16 javascript node.js webpack

我试图了解webpack如何使用DefinePlugin.我有:

new webpack.DefinePlugin({
  'process.env.NODE_ENV': JSON.stringify('development'),
}),
Run Code Online (Sandbox Code Playgroud)

和功能:

export const foo = () => {
  console.log(process)
  console.log(process.env.NODE_ENV)
}
window.foo = foo
Run Code Online (Sandbox Code Playgroud)

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

ƒ foo() {
  console.log(process);
  console.log("development");
}
Run Code Online (Sandbox Code Playgroud)

在webpack编译输入文件时,似乎注入了变量"development".同时webpack还将进程对象注入到JavaScript代码中,浏览器确实在调用foo时打印出进程对象:

{title: "browser", browser: true, env: {…}, argv: Array(0), nextTick: ƒ, …}
Run Code Online (Sandbox Code Playgroud)

我的问题是,如何将流程对象(即Node概念)提供给浏览器?

事实上,如果我这样做:

window.process = process
Run Code Online (Sandbox Code Playgroud)

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

谢谢!

Aut*_*ico 6

这里提到https://webpack.js.org/configuration/node/#node-process的的WebPack可以针对不同节点的功能polyfills,但它显示为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);
    };
})();
Run Code Online (Sandbox Code Playgroud)

从您提供的信息中很难确定。如果它真的有效,我认为您很可能在您的节点应用程序中启用了Browserify。也许你在这里找到了一些你需要的东西:https : //webpack.js.org/loaders/transform-loader/#src/components/Sidebar/Sidebar.jsx

希望你觉得这个答案有些帮助。

最重要的是,我相信它是来自某个地方的 polyfill。


And*_*aro 6

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

默认节点全局变量全局注入的,而定义的常量则在所有代码库中一一进行webpack.DefinePlugin物理替换。

例如:

// 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);
Run Code Online (Sandbox Code Playgroud)

请注意,process.env.NODE_ENVprocess.env.MY_VAR物理上被替换,而process.envprocess 保留它们对注入process 模拟的引用。

webpack.DefinePlugin也能够覆盖模拟process对象(或只是其中的一部分):强大的功能意味着出现意外行为的风险。

来自Webpack 文档

为流程定义值时,优先选择 'process.env.NODE_ENV': JSON.stringify('product') 而不是 process: { env: { NODE_ENV: JSON.stringify('product') } }。使用后者将覆盖进程对象,这可能会破坏与某些期望在进程对象上定义其他值的模块的兼容性。

例如:

// 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!]
Run Code Online (Sandbox Code Playgroud)