Skip to content
This repository has been archived by the owner on Jun 15, 2023. It is now read-only.

Brunch global require conflicts with node local require #1465

Open
herenow opened this issue Aug 2, 2016 · 22 comments
Open

Brunch global require conflicts with node local require #1465

herenow opened this issue Aug 2, 2016 · 22 comments
Labels

Comments

@herenow
Copy link
Contributor

herenow commented Aug 2, 2016

Description

The bundle generated by brunch is not compatible with node's environment, whenever I try to run the bundle in node for server rendering, I get something like:

TypeError: require.register is not a function

It is trying to use node's require, and not brunch's.

Since in node require is in the local context, so it takes precedence over brunch's require, which is places in the global context.

Proposed solution

I think we could rename require to __require__ in commonjs-require-definition/require.js and within the bundle.

We could still export both __require__ and require to the global context.

Or we could remove commonjs-require-definition/require.js from its own scope, so at least inside the bundle it overrides node's require (but this seems nasty).

I'm not sure if there is a better solution :)

Environment

  1. Brunch: 2.8.2
  2. Node: v6.2.0
  3. NPM: 3.8.9
  4. Operating system: OS X El Capitan 10.11.6
@digitalbase
Copy link

I have exactly the same problem
Been trying to throw out gulp (very complex config file) to something more intuitive. Got the jsx to compile but the "TypeError: require.register is not a function" keeps popping up

@digitalbase
Copy link

digitalbase commented Aug 10, 2016

@herenow did you find a workaround to get this working ?

@digitalbase
Copy link

digitalbase commented Aug 10, 2016

@paulmillr i would say this is a bug.

I was convinced by the webpack horror story and your homepage copy. I've spend the last 2 days pulling my hair out getting jsx to compile. Followed simple instructions from the docs and I can't get it to work.

Simple brunch.coffee

module.exports =
    paths:
        public: 'web/backend/'
        watched: [
            'web/backend/js/app/'
        ]
    files:
        javascripts:
            joinTo: {
                'build/prezly-backend-jsx-bundle.js': [
                    'web/backend/js/app/**.jsx'
                ]
            }
    plugins:
        autoReload:
            enabled:
                css: 'on'
                js: 'on'
            host: '69.69.69.1'
            port: 9485
        babel:
            presets: ['es2015', 'react'],
            plugins: ['transform-object-assign', 'transform-object-rest-spread']
            pattern: /\.(es6|jsx)$/

I have a few node modules installed:

npm ls | grep node
│ │ │ └─┬ node-pre-gyp@0.6.29
│ │ │   │ ├── node-uuid@1.4.7
│ │ ├─┬ node-browser-modules@0.1.0
│ ├── eslint-import-resolver-node@0.2.2
│ ├─┬ node-notifier@4.6.0
│ │ │ │ └── node-emoji@0.1.0
│ ├─┬ node.extend@1.1.5
├─┬ node-gyp@3.4.0
├─┬ node-sass@3.8.0
│ ├─┬ node-gyp@3.4.0
│ │ ├── node-uuid@1.4.7
│ │ ├── node-uuid@1.4.7
│ │ │ ├─┬ node-fetch@1.6.0
│ ├─┬ node-sass@3.7.0

But after compiling keep getting 'require is not a function' without any warnings/feedback during build

@paulmillr
Copy link
Contributor

@digitalbase not a bug, because node.js / "isomorphic apps" were never a build target for brunch. I've always used it as a frontend-only tool.

I see your point though. I would say this is high on our radar

@herenow
Copy link
Contributor Author

herenow commented Aug 11, 2016

@digitalbase I couldn't find a workaround for this in node. Since I'm actually doing server rendering in Ruby, I ditched node, and used v8 directly instead.

@digitalbase
Copy link

@paulmillr i don't understand. We're not using node.js / isomorphic apps. It's a PHP application with react/redux client side.

@herenow what do you mean used v8 directly ?

Is there any workaround by maybe changing npm dependencies or changing a few lines of code?

@paulmillr
Copy link
Contributor

@digitalbase if it's react / redux client-side it should be working without issues.

What happens if you change javascripts.joinTo to this?

joinTo: 'build/prezly-backend-jsx-bundle.js'

@digitalbase
Copy link

@paulmillr it's an entire folder full of jsx files. I need to specify web/backend/js/app/**.jsx shouldn't i ?

@paulmillr
Copy link
Contributor

no need to do it.

@digitalbase
Copy link

got it. It was a

import "babel-polyfill";

In one of the jsx files that injected some babel require stuff that wasn't working. Still struggling but I got a step further :-) Thank you!

@overallduka
Copy link

Im having this problem, i have an app that use javascript code generated by brunch and should load in other people websites, the problem is that many websites use require function, so i get this error: Uncaught TypeError: require.register is not a function
Thats very important, has some workround for this right now ?

@campadrenalin
Copy link

@overallduka You can wrap the entire generated JS file in:

var require_old = require;
var define_old = define;
try {
    require = undefined;
    define = undefined;
    // Contents of your original JS file
} finally {
    require = require_old;
    define = define_old;
}

This is, in many ways, a brutally ugly hack. But it does get you some very clean separations in ways that matter. But it's very important to do the whole thing in one script. The sleight of hand fails spectacularly if other JS runs while RequireJS is still hidden under the rug.

@etwark
Copy link

etwark commented Mar 6, 2018

I realize this is an old thread; checking to see if this has been considered for any future release. I have been using grunt for several MEAN projects (frontend and backend compilation targets are different) Would love to switch to Brunch at some point but lack of nodejs support cancels out a lot of the benefits for me. Curious to see if this is planned or is considered "mission creep."

Has anyone else come up with a viable workaround?

@overallduka
Copy link

I have had the same problem, in my case i could solve doing this:

  1. Added the plugin replacement-brunch
  2. In the brunch config i did this:
  plugins: {
    babel: {
      ignore: [/web\/static\/vendor/],
      presets: ['es2015']
    },
    replacement: {
      replacements: [{
        files: [/\.js$/],
        match: {find: /(?!_)\b(require)(?!_|d)/gm, replace: 'MY_REQUIRE'}
      }]
    }
  },

So the require turned into MY_REQUIRE, in my case this solved the problem.

@etwark
Copy link

etwark commented Mar 8, 2018

@overallduka Great idea. I'll give it a try and see what I come up with. Thanks!

@oleggo
Copy link

oleggo commented Jul 23, 2018

It is very hack-ish workaround but it can be suitable for development purposes.
I understand it is pretty easy to integrate it into brunch codebase.
Note that this workaround supports automatic backend reload.
It misses fancy stack trace reporting on errors but it is not a big issue as you can always open file in public folder and go to specified line.

Suppose we have file app/server.js which exports class which has method 'use' accepting the same parameters as expressjs use call, i.e. req, res, next.
Configuration for it looks like this:

javascripts: { entryPoints: { 'app/server.js': 'server.js' }, },

Now, brunch-server.js file looks like this:

const express = require('express');
const app = express();

app.use(express.static(__dirname + '/public'));

module.exports = (config, callback) => {
  app.listen(config.port, function () {
    console.log('Example app listening on port ' + config.port);
    callback();
  });
  return app;
};

const fs = require('fs');
function replaceAll(str, find, replace) {
  return str.split(find).join(replace);
}

const serverModule = 'server.js';
const serverJsFile = './public/' + serverModule;

function replaceFile(file) {
  file = replaceAll(file, 'globals.require', 'globals.require2');
  file = replaceAll(file, 'require.register(', 'require2.register(');
  file = replaceAll(file, 'require.alias(', 'require2.alias(');
  file = replaceAll(file, 'require(\'___globals___\')', 'require2(\'___globals___\')');
  file = replaceAll(file, 'process = require(\'process\')', '');
  return file;
}

function loadServer() {
  let file = fs.readFileSync(serverJsFile, { encoding: 'utf8' });
  file = replaceFile(file);
  new Function(file)();
  const globals = typeof global === 'undefined' ? self : global;
  const req = globals.require2;
  return req(serverModule);
}

let server = null;
let mtime = null;

function getRefreshedServer() {
  let uptime = fs.statSync(serverJsFile).mtime.getTime();
  if (mtime === uptime) {
    return server;
  }
  mtime = uptime;
  console.log('Reloading ' + serverJsFile);
  const sclass = loadServer().default;
  server = new sclass();
  return server;
}

app.all('/api/*', function(req, res, next) {
  getRefreshedServer().use(req, res, next);
});

@paulmedynski
Copy link

I have some patches to commonjs-require-definition and deppack that work for me. I can work them into something that brunch does without needing to modify those modules. It would be optional behaviour. Can someone assign this ticket to me?

@paulmillr
Copy link
Contributor

Easy. But I cannot assign your profile somehow. Go ahead please!

@paulmedynski
Copy link

Probably need to be a contributor on this project.

@paulmillr
Copy link
Contributor

@paulmedynski I have no problem with giving you maintainer rights, just want to ensure that's sustainable. Please develop pull requests first.

@paulmedynski
Copy link

Yep, understood. I'm new to GitHub, so I was just guessing that you can't assign this issue to me unless I'm a contributor or something similar of this project. Too bad really, since it would be nice to make it obvious someone is working on an issue, even if they aren't a contrib of the project.

@reubano
Copy link
Contributor

reubano commented Dec 17, 2018

@paulmedynski I think you miss-understood what @paulmillr is saying. Anyone can create a pull request (PR), you don't have to be a maintainer. Once you successful create a PR, he will then be open to giving you commit access. Many projects operate this way to limit maintainer rights to those who have actually contributed to the project.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Development

No branches or pull requests

9 participants