【问题标题】: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 不执行它捆绑的代码。您要么在运行时在浏览器或服务器中执行代码,所以只有检查它是在浏览器还是服务器中运行很重要,对吧?

标签: javascript node.js reactjs 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;
      }
      

      【讨论】:

        猜你喜欢
        • 2019-11-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-30
        • 2023-03-17
        相关资源
        最近更新 更多