swagger-api/swagger-codegen

[Javascript] webpack fail with resolving AMD module

Closed this issue ยท 8 comments

Description

My Test Repository

My package link to a js codegen project.
When webpack build a bundle, it fail with the AMD define.
If I change the AMD path to CommonJS path, it pass. (see FIXME)

if (typeof define === 'function' && define.amd) {
    // AMD. Register as an anonymous module.
    define(['ApiClient', 'api/DefaultApi'], factory);
   // FIXME define(['./ApiClient', './api/DefaultApi'], factory);
} else if (typeof module === 'object' && module.exports) {
    // CommonJS-like environments that support module.exports, like Node.
    module.exports = factory(require('./ApiClient'), require('./api/DefaultApi'));
}

Error message:

ERROR in ./packages/minimal/src/index.js
Module not found: Error: Cannot resolve module 'ApiClient' in /Users/lin/git/swagger/webpack_minimal/packages/minimal/src
 @ ./packages/minimal/src/index.js 32:4-52

When it pass, ApiClient.js raise an another error.

// fs.ReadStream in Node.js (but not in runtime like browserify)
if (typeof window === 'undefined' &&
    typeof require === 'function' &&
    require('fs') &&
    param instanceof require('fs').ReadStream) {
  return true;
}
ERROR in ./packages/minimal/src/ApiClient.js
Module not found: Error: Cannot resolve module 'fs' in /Users/lin/git/swagger/webpack_minimal/packages/minimal/src
 @ ./packages/minimal/src/ApiClient.js 103:74-87 103:108-121
Swagger-codegen version

master branch > 2.1.6

Swagger declaration file content or url
swagger: '2.0'
info:
  version: 1.0.0
  title: Minimal API
paths:
  /:
    get:
      responses:
        200:
          description: OK
Command line used for generation
java -jar path/to/jar generate -i minimal.yaml -o packages/minimal -l javascript --additional-properties emitJSDoc=false,usePromises=true
Steps to reproduce

git clone https://github.com/sherdeadlock/minimal-webpack-swagger
cd minimal-webpack-swagger
npm link packages/minimal
npm install
node server.js

Related issues
Suggest a Fix

I fix the problem by configuring webpack.

Disable AMD

add imports?define=>false
example commit

module: {                                                                     
    loaders: [                                                                  
      {                                                                         
        test: /\.js$/,                                                          
        loaders: [                                                              
          'babel',                                                                                                                                          
          'imports?define=>false'                                               
        ],                                                                      
        exclude: /node_modules/,                                                
        include: __dirname                                                      
      },                                                                        
    ]                                                                           
  }

Mock fs module

add fs: 'empty'
example commit

  node: {
    fs: 'empty'
  },

@sherdeadlock thanks for reporting the issue and sharing the fix.

I found that if I modified the index.js file such that the code (borrowed from @sherdeadlock's initial post above) with the define method can be modified to include "./" before each file name like this:
define(['./ApiClient', './api/DefaultApi'], factory);
this seemed to "fix" the compilation of that file.

@sfncook Here is a similar answer on updating webpack config: #3466 (comment)

Does adding "./" break the existing solution/workaround (updating webpack config)?

If it doesn't, we can add "./" as a permanent solution by updating the JS mustache template.

@wing328 I'll try to check your request when I have a moment.

In the meantime, I implemented @sherdeadlock's suggestion above to disable the 'define' amd method. However, I had to use a slightly different syntax in my webpack config because we're using us a query parameter with our babel loader:

module: { loaders: [ { test: /tripod-sdk/, loader: 'imports?define=>false', }, { test: /\.(js|jsx)$/, include: paths.appSrc, loader: 'babel', query: require('./babel.dev') }, ...

Also note that the "imports" loader is installed with the "imports-loader" npm package. <-- this is a note for n00bs like myself.

frol commented

One extra note: Webpack 2 requires using imports-loader loader full name instead of a short name (imports). Thus, here is what works for me for Webpack 2:

module: {
  rules: [
    {
      test: /my_client\/.*\.js$/,
      use: 'imports-loader?define=>false'
    }
  ]
},
node: {
  fs: 'empty'
}

Hi, I really don't like asking my users to manually update their webpack config just so they can use my API client library. I managed to fix this issue by adding ./ and ../ to make them relative paths. (I've overridden the mustache templates.) Is there any reason why this isn't a good idea?

This is especially important for create-react-app apps, because the webpack config can't be easily changed.

I've created a PR to change the mustache templates with the correct relative paths
#9662