Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Browserify-ed code on a server: how to get "window", "location" and other "window" properties and typically browser objects?

I want to use browserified code both, in a browser and on a server. My code is basically React components. I want to browserify the code, get one compiled sheet app.js and use it both, in a browser and on a server:

// in a browser
<script src="/js/app.js" type="text/javascript" charset="utf-8" async></script>

// on a server
var App = require('../assets/js/react/app');

But browserify doesn't know window object as I understand. I cannot require browserified code in a server side, an error is thrown:

if (window.location.pathname == '/foo') {
    ^
ReferenceError: window is not defined

Here is code:

... many React components go here ...

// and here is a call to window and its properties
if(window.location.pathname == '/foo') {
    ReactDOM.render(
        <MsgBox data={window.data} oInfo={window.oInfo} />,
        document.getElementById('content-body')
    );

    ReactDOM.render(
        <SearchBox />,
        document.getElementById('searchBox')
    );
}

browserify-handbook says that global is an alias for the window:

In node, global is the top-level scope where global variables are attached similar to how window works in the browser. In browserify, global is just an alias for the window object.

I tried to change but then get another error TypeError: Cannot read property 'pathname' of undefined:

// the code, I change window to global
if(global.location.pathname == '/foo') {
    ...
}

// and an error
if (global.location.pathname == '/foo') {
                   ^
TypeError: Cannot read property 'pathname' of undefined

So how to deal with window in such a case?

One thought is to use a variable, which I do now:

var isBrowser;
if(typeof window != 'undefined') {
    isBrowser = true
}
else 
    isBrowser = false;

But is it the best way? It looks a little bit odd to me. Is there special means in Browserify for window and other native browsers only objects? What is the best practice to use Browserify in such a case?

like image 471
Green Avatar asked Dec 23 '15 02:12

Green


1 Answers

You are going to have trouble doing it that way.

It reminds me of Delphi's runtime / design-time packages that contain a lot of

if (state in csDesigning) do 
begin 
    ... // Bad juju 
end
else do 
begin
    ... // Bad juju
end

Not a good idea. You'll lose your mind in the long run. Instead, create a shared kernel that will contain your shared code, nothing else. The window variable should never be seen by the server.

browser.js
common.js // shared kernel (browserify)
server.js
like image 153
Ludovic C Avatar answered Sep 19 '22 11:09

Ludovic C