我可以检测我的脚本是不是正在被 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 && typeof process.env === 'object' && 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?