KidkArolis / jetpack

🚀 Jetpack – Webpack made more convenient.
1.31k stars 30 forks source link

Pure backend: got errors "Module not found: Can't resolve..." #47

Closed tomsquest closed 5 years ago

tomsquest commented 5 years ago

I have a "simple" Nodejs API, using Nestjs. When running Jetpack, the console and the webpage generate Module not found: Can't resolve errors.

Sample error:

$ npm run start:jet

> api@0.0.0 start:jet /home/tom/Dev/api
> jetpack ./src/main.ts

jetpack › Jetpack 0.12.1 🚀
jetpack › Webpack 4.29.0
jetpack › Dir /home/tom/Dev/api
jetpack › Entry ./src/main.ts
jetpack › Asset server http://localhost:8080
jetpack › Failed to compile! Found 1 error:

  ./node_modules/@grpc/grpc-js/build/src/channel.js
  Module not found: Can't resolve '../../package' in '/home/tom/Dev/api/node_modules/@grpc/grpc-js/build/src'

The UI at localhost:8080 shows a lot more errors of the same kind (Module not found: Error: Can't resolve 'fs' in '/home/tom/Dev/api/node_modules/glob')

jetpack.config.js (from Jetpack doc, except for entry/port/verbose).

module.exports = {
  // dir: 'src',
  entry: 'src/main.ts',
  port: 8080,
  verbose: true,
  webpack (config) {
    config.resolve.extensions = ['.tsx', '.ts', '.js']
    config.module.rules[0].oneOf.push({
      test: /\.tsx?$/,
      loader: 'ts-loader',
      exclude: /node_modules/,
    })
  }
}

tsconfig.json (default from Jetpack doc)

{
  "compilerOptions": {
    "target": "es5",
    "allowJs": true,
    "skipLibCheck": false,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "react"
  },
  "include": [
    "src"
  ]
}

Project structure:

If you have an idea, I would be please to try it.

Thanks.

KidkArolis commented 5 years ago

Hm, strange. It's interesting it looks like something is requiring fs module, which shouldn't be happening for a web project. I think webpack stopped including node built ins like fs since version 4.

First thing I would try in your place:

  1. In your entry point main.ts comment out all of the code, see it it builds ok
  2. Uncomment imports one by one and see which one breaks
  3. Then when it breaks, do the same for that module and so on

This way you might be able to identify which specific import is failing? That would be useful to know.

tomsquest commented 5 years ago

I don't think there is a wrong import.

The project is working when run with this webpack.config.js (that enables HMR and debugging from Jetbrains products):

const webpack = require('webpack');
const path = require('path');
const nodeExternals = require('webpack-node-externals');
const WebpackShellPlugin = require('webpack-shell-plugin');

// WebpackShellPlugin does not handle double-space in commands, so strip them
const serverCmd = `node ${process.env.NODE_DEBUG_OPTION || ''} dist/server`
  .replace('  ', ' ')

module.exports = {
  entry: ['webpack/hot/poll?1000', './src/main.ts'],
  watch: true,
  target: 'node',
  externals: [
    nodeExternals({
      whitelist: ['webpack/hot/poll?1000'],
    }),
  ],
  devtool: 'inline-source-map',
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: 'ts-loader',
        exclude: /node_modules/,
      },
    ],
  },
  mode: "development",
  resolve: {
    extensions: ['.tsx', '.ts', '.js'],
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new WebpackShellPlugin({onBuildEnd: [serverCmd]})
  ],
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'server.js',
  },
};

Note that there is a webpack target: node option. I tried this in jetpack.config.js but it did not change anything.

KidkArolis commented 5 years ago

I guess I didn't mean there's a wrong import, just it would be useful to know which import is the cause for the error so I could try and reproduce.

The bit of the config about target node. Is this how you tried adding it to jetpack.config.js?

module.exports = {
  webpack: (config, options) => {
    Object.assign(config, {
      target: 'node'
    })
  }
}
tomsquest commented 5 years ago

Same problem with: Object.assign than with config.target = 'node'.

So far, there is a blank page at localhost:8080 and this error on the console:

Module not found: Can't resolve '../../package' in '/home/tom/Dev/api/node_modules/@grpc/grpc-js/build/src'

@grpc is a dependency on google-auth-library which is used for user authentication.

KidkArolis commented 5 years ago

With this config:

module.exports = {
  webpack (config) {
    config.target = 'node'
  }
}

this entry point:

import auth from 'google-auth-library'
console.log(auth)

builds with this command:

$ jetpack build

And if I comment out target = 'node', I get:

jetpack › Failed to compile! Found 1 error:

  ./node_modules/google-auth-library/build/src/auth/googleauth.js
  Module not found: Can't resolve 'child_process' in '/Users/karolis/Desktop/jetpack-issue-47/node_modules/google-auth-library/build/src/auth'

But even when it does build, I'm not sure how this is meant to work in node, since jetpack splits code over multiple bundles and separates the runtime chunk. If I require those files in node, nothing happens, nothing gets logged. I've just never really compiled node code with webpack before.

Is the idea here to try and run this Nestjs API but with HMR? I usually use nodemon, so don't have much experience with this.

Thanks for providing as much info as you have already, any chance you could provide the full project source? Or a full reproducable example?

tomsquest commented 5 years ago

Is the idea here to try and run this Nestjs API but with HMR? I usually use nodemon, so don't have much experience with this.

Yes, that was basically the idea. When I discovered Jetpack I was thinking a being able to remove any config file related to building and still offer hot-reload and HMR.

Thanks for providing as much info as you have already, any chance you could provide the full project source? Or a full reproducable example?

This is a private-corporate project.

I will close this issue, as I think Jetpack is not for this kind a use-case (nodejs api).

KidkArolis commented 5 years ago

Yeah, it really was built with Single Page Apps + Node.js API (separately) in mind, e.g. if you have this package.json:

"main": "server.js",
"browser": "client.js"

And run jetpack -x it will run both client (bundling and serving via webpack) and server (simply executing it as node server.js without compiling anything). This way you get a SPA running in the browser that can also connect back to your API.

This was sort of the primary use case for jetpack. But it can generally be used in a variety of ways, in particualar the server bit is optional, since you might be using serverless, firebase, another language, etc.

But compiling the server code is not something I've done much before, sorry you ran into difficulties. Thanks for checking out the project and providing useful info on different use cases 🙏.