parcel-bundler / parcel

The zero configuration build tool for the web. 📦🚀
https://parceljs.org
MIT License
43.5k stars 2.27k forks source link

TypeError: module.require is not a function #3776

Open northern opened 4 years ago

northern commented 4 years ago

🐛 bug report

🎛 Configuration (.babelrc, package.json, cli command)

{
  "name": "test",
  "version": "0.0.0",
  "author": "",
  "license": "UNLICENSED",
  "description": "",
  "main": "src/index.js",
  "scripts": {
    "dev": "nodemon --inspect src/index.js",
    "start": "NODE_ENV=production node bin/index.js",
    "dist": "parcel build ./src/index.js -d ./bin --target node --no-source-maps --bundle-node-modules"
  },
  "dependencies": {
    "graphql": "^14.2.1",
    "apollo-server": "^2.9.9",
    "apollo-server-koa": "^2.9.9",
    "koa": "^2.7.0",
    "koa-router": "^7.4.0"
  },
  "devDependencies": {
    "concurrently": "^4.1.0",
    "dotenv": "^8.2.0",
    "nodemon": "^1.17.2",
    "parcel-bundler": "^1.12.3"
  }
}

🤔 Expected Behavior

I expect the compiled prod server to start just like the dev server does.

😯 Current Behavior

When I build my node project with the --bundle-node-modules option and then when I run the project, I get the following error:

TypeError: module.require is not a function
    at Object.r [as default] (/Users/northern/temp/parcel/bin/index.js:550:226)
    at Object.s [as generateSchemaHash] (/Users/northern/temp/parcel/bin/index.js:706:1028)
    at f.generateSchemaDerivedData (/Users/northern/temp/parcel/bin/index.js:1088:147)
    at new E (/Users/northern/temp/parcel/bin/index.js:1076:5165)
    at new f (/Users/northern/temp/parcel/bin/index.js:1204:1521)
    at Object.parcelRequire.Focm.koa (/Users/northern/temp/parcel/bin/index.js:1212:42)
    at f (/Users/northern/temp/parcel/bin/index.js:1:468)
    at parcelRequire.HTqd (/Users/northern/temp/parcel/bin/index.js:1:771)
    at Object.<anonymous> (/Users/northern/temp/parcel/bin/index.js:1:1023)

However, without the --bundle-node-modules option, the project runs as expected (but I require the single compiled index.js).

💁 Possible Solution

N/A

🔦 Context

I spend a fair bit of time trying to figure out how to resolve this issue but I clearly need some expert help.

💻 Code Sample

To reproduce, use the following directory structure:

package.json
src/index.js
bin/
// src/index.js

const Koa = require('koa');
const { ApolloServer, gql } = require('apollo-server-koa');

// Construct a schema, using GraphQL schema language
const typeDefs = gql`
  type Query {
    hello: String
  }
`;

// Provide resolver functions for your schema fields
const resolvers = {
  Query: {
    hello: () => 'Hello world!',
  },
};

const server = new ApolloServer({ typeDefs, resolvers });

const app = new Koa();
server.applyMiddleware({ app });
// alternatively you can get a composed middleware from the apollo server
// app.use(server.getMiddleware());

app.listen({ port: 4000 }, () =>
  console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`),
);

To run dev server use: npm run dev. Browse to localhost:4000/graphql will bring up the GraphQL Playground.

To build the prod server use: npm run dist. This will place the compiled server in bin/index.js

To run the prod server use: npm run start. This will exit with error:

TypeError: module.require is not a function

🌍 Your Environment

Software Version(s)
Parcel ^1.12.4
Node 12
npm/Yarn npm 6.10.3
Operating System MacOS
mischnic commented 4 years ago

Building with --no-minify throws yet another error:

Error: Cannot use GraphQLObjectType "Query" from another module or realm.

Ensure that there is only one instance of "graphql" in the node_modules
directory. If different versions of "graphql" are the dependencies of other
relied on modules, use "resolutions" to ensure only one version is installed.

https://yarnpkg.com/en/docs/selective-version-resolutions

Duplicate "graphql" modules cannot be used at the same time since different
versions may have different capabilities and behavior. The data from one
version used in the function from another could produce confusing and
spurious results.

(Related issue: https://github.com/parcel-bundler/parcel/issues/2327)

jcane86 commented 4 years ago

I ran into this same issue with apollo-server-lambda.

Related issue here apollographql/apollo-server#3808

Apollo is using module.require to load node's crypto library in node-like environments: https://github.com/apollographql/apollo-server/blob/8b02c0c440928d6b1d4e8c6d79a9d27f2a528666/packages/apollo-server-core/src/utils/createSHA.ts#L7

I just had a quick look, not familiar with Parcel internals, but looks like the modules created by Parcel dont include module.require https://github.com/parcel-bundler/parcel/blob/d24e09a9797af41a9d2c6c733b1c6cf6671d60c7/packages/core/parcel-bundler/src/builtins/prelude.js#L45

Any ideas?

srghma commented 4 years ago

in my case, I'm getting this error because module.require is tree-shaked to null, but should be undefined

why this happens

I'm using purescript-debug library, which should work on both browser and node

it has these lines

// Alias require to prevent webpack or browserify from actually requiring.
var req = typeof module === "undefined" ? undefined : module.require;
var util = req === undefined ? undefined : req("util");

webpack tree shakes this to undefined, so this works fine

(NOTE: I didnt check for sure how webpack transformes, but I remember it works fine with purescript-debug)

but parcel:

  1. with --no-minify compiles to
// Alias require to prevent webpack or browserify from actually requiring.
var $Ttyb$var$req = "object" === "undefined" ? undefined : null;
var $Ttyb$var$util = $Ttyb$var$req === undefined ? undefined : $Ttyb$var$req("util");
  1. without --no-minify it compiles AND tree shakes to
    var UA = null
      , VA = void 0 === UA ? void 0 : UA("util")

as you see if UA = undefined - it would tree-shake even further to VA = void 0

EXPECTED IS

module.require should be transformed to undefined (not to null)