blog_robinwieruch_content icon indicating copy to clipboard operation
blog_robinwieruch_content copied to clipboard

Sequelize and Webpack not playing nice together

Open michaelyiu opened this issue 5 years ago • 11 comments

I have to say, this tutorial is a godsend. I love the breakdowns and very clear-cut explanations and I just so happen to need to use most of the packages.

I was following the guide fairly well until the Sequelize part of the tutorial and I was getting an error: "Cannot find module C:\PROJECT_DIR\\.webpack\service\src\user" for the user file. I've tried the following:

const models = [ 'User', 'Message' ];

models.forEach(function(model) { module.exports[model] = sequelize.import(__dirname + '/' + model); });

But when I ran it again, "Cannot find module 'C:\User'"

  1. Sequelize as a nodeExternal

  2. Adding this piece to webpack.config.js node: { __dirname: false },

Error: "Cannot find module C:\PROJECT_DIR\\.webpack\service\src\user"

  1. There has been some examples around google such as https://gist.github.com/ihavenoidea14/0dab8b461c057c427829fdc99bfb6743 https://github.com/webpack/webpack/issues/4879

that uses module(sequelize, Sequelize); When I tried the examples in the links above, I get a 'module is not a function'.

I'm at a loss and am wondering if you had tried with Webpack before and if you have any recommendations I'd love to hear it.

Cheers.

michaelyiu avatar Dec 14 '18 05:12 michaelyiu

Can you maybe link your GitHub repository here? Then I can check whether I can help with it!

rwieruch avatar Dec 14 '18 05:12 rwieruch

https://github.com/michaelyiu/apollo-server-tutorial

I forgot to mention I'm using it with serverless as well

Turns out finding a different way to import the models seem to do the trick and I didn't have to play around with webpack too much

michaelyiu avatar Dec 14 '18 06:12 michaelyiu

@michaelyiu did you find the cause? Sorry for not being able to fix this in time.

rwieruch avatar Dec 21 '18 00:12 rwieruch

@michaelyiu, could you by any chance elaborate on "different way to import the models"?

radcapitalist avatar Jan 29 '19 13:01 radcapitalist

@michaelyiu, could you by any chance elaborate on "different way to import the models"?

@radcapitalist sorry for the extremely late reply. So for whatever reason, I couldn't mimic what @rwieruch had in his post because webpack was complaining:

 User: sequelize.import('./user'),
 Message: sequelize.import('./message'),
};

Object.keys(models).forEach(key => {
 if ('associate' in models[key]) {
   models[key].associate(models);
 }
});`

I had to require the files in the /model/index first:

`const userModel = require("./User.js");
const messageModel = require("./Message.js");

const models = {
	User: sequelize.import("user", userModel),
	Message: sequelize.import("message", messageModel),
}

Object.keys(models).forEach(key => {
	if ("associate" in models[key]) {
		models[key].associate(models);
	}
})

It gets a bit tedious the more models I had to put in but hey it works.

michaelyiu avatar Mar 06 '19 23:03 michaelyiu

Okay, I ended up going with the require.context() approach suggested here:

https://github.com/sequelize/express-example/issues/74

It keeps you from having to enumerate every individual model file, allowing you instead to process *.js (excluding index.js) from your models folder just like you probably did before Webpack. I have models from two folders (one that is shared with another project), so my code looks like this:

const modelsContext = require.context('.', false, /^\.\/(?!index\.js).*\.js$/, 'sync');
debug(`modelsContext: ${JSON.stringify(modelsContext.keys())}`);
const sharedModelsContext = require.context('../../../../../shared/models/postgres', false, /^\.\/(?!index\.js).*\.js$/, 'sync');
debug(`sharedModelsContext: ${JSON.stringify(sharedModelsContext.keys())}`);

modelsContext.keys().map(modelsContext).forEach(module => {
	const model = module(sequelize, Sequelize);
	debug(`postgres: About to import model: ${model.name}`);
	db[model.name] = model;
});

sharedModelsContext.keys().map(sharedModelsContext).forEach(module => {
	const model = module(sequelize, Sequelize);
	debug(`postgres: About to import model: ${model.name}`);
	db[model.name] = model;
});


Object.keys(db).forEach(function(modelName) {
	if ("associate" in db[modelName]) {
		db[modelName].associate(db);
	}
});

radcapitalist avatar Mar 07 '19 13:03 radcapitalist

Clean, I'm gonna try this out!

michaelyiu avatar Mar 07 '19 18:03 michaelyiu

Do you think more people using Webpack are running into this issue? Then I would keep it open for now. Let me know!

rwieruch avatar Mar 16 '19 13:03 rwieruch

Yeah, I definitely think a large majority running Webpack would run into this issue. Also I've been running into several issues trying to get the above by @radcapitalist to work because I added helper methods inside the model itself in case anyone stumbles onto this and wonders why. Refactoring that code into the resolvers or some helper file is probably better.

I also changed the index files in resolvers/schemas which was much simpler

const context = require.context('.', true, /^./(?!index.js).*.js$/, 'sync');

let schemas = [];

const linkSchema = gql`
  scalar Date

  type Query {
    _: Boolean
  }
  type Mutation {
    _: Boolean
  }
  type Subscription {
    _: Boolean
  }
`;
schemas.push(linkSchema)

context.keys().forEach(module => {
  schemas.push(context(module).default)
});

export default schemas

Thanks again @radcapitalist for the super clean solution

edit: It wasn't about the helper methods that's preventing this solution, it's actually the associations. Which I'm having issues circumventing.

michaelyiu avatar Mar 17 '19 21:03 michaelyiu

@michaelyiu did you ever get around the associations issues you had? I submitted a similar issue to what you're describing on the sequelize repo https://github.com/sequelize/sequelize/issues/12874

AwolDes avatar Nov 29 '20 05:11 AwolDes

Hello, everyone! I've just created a new related issue: https://github.com/sequelize/sequelize/issues/13169

papb avatar Apr 04 '21 22:04 papb