我可以检测我的脚本是不是正在被 Webpack 处理吗?

Posted

技术标签:

【中文标题】我可以检测我的脚本是不是正在被 Webpack 处理吗?【英文标题】:Can I detect if my script is being processed by Webpack?我可以检测我的脚本是否正在被 Webpack 处理吗? 【发布时间】:2015-11-19 22:25:49 【问题描述】:

我正在尝试在 React 中使用同构渲染,以便可以将静态 html 作为文档输出为我的应用程序。

问题是我有一个仅在客户端上运行的特定组件,因为它引用了window。解决方案很明显:不在服务器上渲染它。是的,我不能在服务器上渲染它,但我仍然需要将它包含在我的webpack 包中,以便我可以在客户端上渲染它。问题是,阻止我的组件在服务器上呈现的代码是:

function isServer() 
    return ! (typeof window != 'undefined' && window.document);

但是当webpack 捆绑时isServer() 也是true,我希望它在webpack 运行时正常工作。

那么,我如何检测webpack 正在运行?

我正在寻找这样的东西:

function isWebpack() 
    // what do I put here?

如果isServer()!isWebpack(),现在我可以正常渲染我的客户端组件。

谢谢!

编辑

这是我正在尝试构建的组件:

function isServer() 
    return ! (typeof window != 'undefined' && window.document);


import React from 'react';

const LED = React.createClass(

    render: function () 

        if(!isServer()) 
            var LiveSchemaEditor  = require('../../src/components/LiveSchemaEditor.js');
            return <LiveSchemaEditor />;
        

        return <div>I AM IN THE SERVER</div>;
    
);

export default LED;

困扰我的是webpack 包包含LiveSchemaEditor.js 的内容,但在客户端时仍会打印I AM IN THE SERVER。这没有意义。

【问题讨论】:

会检查一些节点-y 工作吗? function isNode() return process &amp;&amp; typeof process.env === 'object' &amp;&amp; Object.keys(process.env).length; 在浏览器上,返回 0,但在节点中运行,它将 > 0。或者只是查找以下任何一个:nodejs.org/docs/latest/api/process.html#process.version @m59,谢谢,但在服务器渲染时也会返回 true。我需要只有在 webpack 正在运行时才返回 true 的东西。如果我可以在 webpack 运行时专门设置 process.env.NODE_ENV,那就可以了。 我不使用 webpack,所以你能告诉我如何设置你所指的情况吗? Webpack 实际上是在执行你的代码吗? 这对你来说会有点困难,因为你不习惯它:)。 Webpack 是一个打包工具。它遍历 CommonJs require 语句以构建 javascript 文件树并输出结果包。感谢您提供帮助。 我一直在使用browserify,之前也使用过webpack。应该不难。我不明白 webpack 本身将如何在捆绑过程中运行您的功能。 Webpack 不执行它捆绑的代码。您要么在运行时在浏览器或服务器中执行代码,所以只有检查它是在浏览器还是服务器中运行很重要,对吧? 【参考方案1】:

把它放在你的 webpack 配置中的插件下:

new webpack.DefinePlugin(
    'process.env': 
        NODE_ENV: JSON.stringify('production'),
        APP_ENV: JSON.stringify('browser')
    
),

您可以通过这种方式检查您是否在浏览器中运行:

if (process.env.APP_ENV === 'browser') 
    const doSomething = require('./browser-only-js');
    doSomething();
 else 
    const somethingServer = require('./server-only-js');
    somethingServer();


if (process.env.APP_ENV !== 'browser') 
    const somethingServer = require('./server-only-js');
    somethingServer();

因为这些环境变量在构建过程中会被替换,所以 Webpack 不会包含仅服务器的资源。您应该始终以简单的方式做这些事情,并进行简单直接的比较。 Uglify 将删除所有死代码。

由于您之前使用过一个函数并且在构建过程中没有评估该函数,Webpack 无法知道它可以跳过什么要求。

NODE_ENV-变量在生产模式下应始终设置为production,因为包括 React 在内的许多库都使用它进行优化。)

【讨论】:

最后那个关于 NODE_ENV 环境变量的标签看起来很有价值,我担心我在某个明显的地方错过了它。我应该在哪里看到它?也许我没有看到它,因为我碰巧没有使用这些库? @BaldEagle,它列在 React 下载页面的 NPM 部分:facebook.github.io/react/downloads.html#npm - 我只是觉得很少有人再读它了。 这是答案的一部分:我还没有使用 React。那个时候快到了。如果有帮助,我做了一些网络搜索,发现这很有趣:link 感谢您的写作。 如果您将其作为对象传递给DefinePlugin,您最终将重写整个NODE_ENV。而是:"process.env.NODE_ENV": JSON.stringify(...), "process.env.APP_ENV": ...【参考方案2】:

你也可以这样做 -

typeof __webpack_require__ === 'function'

我猜这可能会随时发生变化,因此请谨慎使用。 :/

【讨论】:

【参考方案3】:

更改 render() 的输出会导致 react 无法为组件补水,因此服务器端渲染将被丢弃。

请考虑使用专门在浏览器中运行的 ComponentDidMount

//file level const (cache the result)
let LiveSchemaEditor = () => null;

//...

componentDidMount() 
    LiveSchemaEditor  = LiveSchemaEditor || require('../../src/components/LiveSchemaEditor.js');
    this.setState( editor: <LiveSchemaEditor/> );


render() 
    if(!this.state.editor)
        return <div>loading...</div>;
    

    return this.state.editor;

【讨论】:

【参考方案4】:

这对我有用。

if(typeof process.env.NODE_ENV === "undefined") 
    // Not webpack
 else 
    // Its webpack

【讨论】:

这行不通,在我的单元测试中NODE_ENV'test',我使用nyc + ava【参考方案5】:

在 Node.js 中 global.global 是循环引用,Webpack 没有创建这个循环:

function is_node() 
    return typeof global !== 'undefined' && global.global === global;

【讨论】:

以上是关于我可以检测我的脚本是不是正在被 Webpack 处理吗?的主要内容,如果未能解决你的问题,请参考以下文章

检测两个按钮是不是被按住

使用 Webpack,是不是可以只生成 CSS,不包括 output.js?

“配置”脚本如何检测我的系统是不是支持某些头文件或 cpp 功能?

如何让我的对象检测它是不是被点击?

如何检测服务器是不是正在使用 SPDY

Java - 检测鼠标是不是在屏幕上的任何位置按下