New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Brunch global require conflicts with node local require #1465

Open
herenow opened this Issue Aug 2, 2016 · 21 comments

Comments

Projects
None yet
8 participants
@herenow
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

@paulmillr paulmillr added the feature label Aug 10, 2016

@digitalbase

This comment has been minimized.

digitalbase commented Aug 10, 2016

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

This comment has been minimized.

digitalbase commented Aug 10, 2016

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

@digitalbase

This comment has been minimized.

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

This comment has been minimized.

Member

paulmillr commented Aug 10, 2016

@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

This comment has been minimized.

Contributor

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

This comment has been minimized.

digitalbase commented Aug 11, 2016

@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

This comment has been minimized.

Member

paulmillr commented Aug 11, 2016

@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

This comment has been minimized.

digitalbase commented Aug 11, 2016

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

@paulmillr

This comment has been minimized.

Member

paulmillr commented Aug 11, 2016

no need to do it.

@digitalbase

This comment has been minimized.

digitalbase commented Aug 11, 2016

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

This comment has been minimized.

overallduka commented Oct 27, 2016

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

This comment has been minimized.

campadrenalin commented Jun 1, 2017

@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

This comment has been minimized.

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

This comment has been minimized.

overallduka commented Mar 8, 2018

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

This comment has been minimized.

etwark commented Mar 8, 2018

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

@oleggo

This comment has been minimized.

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

This comment has been minimized.

paulmedynski commented Nov 18, 2018

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

This comment has been minimized.

Member

paulmillr commented Nov 18, 2018

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

@paulmedynski

This comment has been minimized.

paulmedynski commented Nov 19, 2018

Probably need to be a contributor on this project.

@paulmillr

This comment has been minimized.

Member

paulmillr commented Nov 20, 2018

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

@paulmedynski

This comment has been minimized.

paulmedynski commented Nov 21, 2018

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment