Describe the issue
Currently, the library provides no documentation on how to implement hot module reloading in combination with Webpack. Is it even possible? If so, how can one achieve this?
Are you able to make a PR that fix this?
At the moment, just looking for a hotfix.
index.ts
import "reflect-metadata";
import { ApolloServer } from "apollo-server";
import { environment } from "./Environment";
import { buildSchema } from "type-graphql";
import BoardResolver from "./types/boards/BoardResolver";
async function bootstrap() {
const schema = await buildSchema({
resolvers: [BoardResolver]
});
const server = new ApolloServer({
schema
});
server.listen(environment.port).then(({ url }) => {
console.log(`Server is ready at ${url}`);
});
if (module.hot) {
module.hot.accept();
module.hot.dispose(() => server.stop());
}
}
bootstrap();
Result
Every time I reload a type, the module throws this error:
UnhandledPromiseRejectionWarning: Error: Schema must contain unique named types but contains multiple types named "Board".
Every time I reload a type, the module throws this error:
I think it's not possible for now - see more in #234.
how to implement hot module reloading in combination with Webpack. Is it even possible? If so, how can one achieve this?
I would like to know too 馃槃
How is it better than nodemon or ts-node-dev?
That hint was good enough to push me in the right direction. I currently ditched the all-Webpack approach to reload the compiled main.js file with Nodemon. Webpack is a really good build tool which confines to the way JavaScript currently works: modules.
I can import any file and it will be compiled to a JavaScript-compatible module. This goes for CSS, YAML configuration, Handlebar templates, et cetera. Not saying the tool needs to compatible to support those, but a better compatibility with Webpack (hot reloading) would be nice.
@DevNebulae hi there. Can I take a look at your webpack config? I have troubles with type-graphql. I created the most basic example with webpack and after building it I have my type destroyed:

But when I build with tsc -b everything is fine:

So when I create additional resolvers I get buildSchema errors and my guess is it's because of the omitted types.
I don't need HMR, just bundling, that's why I am asking.
Latest versions of all packages.
My webpack config:
```const path = require("path");
const nodeModule = require("webpack-node-externals");
const resolve = pth => path.resolve(__dirname, pth);
const nodeExternals = nodeModule();
module.exports = {
entry: "./src/index.ts",
target: "node",
module: {
rules: [
{
test: /.ts?$/,
use: "ts-loader",
exclude: /node_modules/
}
]
},
resolve: {
extensions: [".ts"],
modules: [resolve("src"), "node_modules"]
},
output: {
filename: "app.js",
path: resolve("dist")
},
externals: [nodeExternals]
};
I had the same issue as you were having (never bothered to run the production build yet). What happens is that Webpack in production mode mangles the class and functions names. Meaning that they are shortened to a single letter. In my case, this lead to naming conflicts. I would recommend reading this: https://webpack.js.org/plugins/terser-webpack-plugin/.
I had the same issue as you were having (never bothered to run the production build yet). What happens is that Webpack in production mode mangles the class and functions names. Meaning that they are shortened to a single letter. In my case, this lead to naming conflicts. I would recommend reading this: https://webpack.js.org/plugins/terser-webpack-plugin/.
You were right, thanks for your help!
Hi @DevNebulae, I had the same issue with the hot reload and maybe the solution that I found is suitable for your case. Take a look to this repo Typegraphql Hot Reload.
Any constructive feedback is welcome.
Regards.
@ddialar In which part it is hot reload? It just restart the whole node server on bundle.js change, not update only the schema part on the fly.
Hi @19majkel94, maybe we don't understand the same by _hot-reload_ but in my repo's code, with webpack running, if I open the _recipe-type.ts_ file and I comment the _description_ field, after saving the file, the server is reloaded, that's true, but the _schema.graphql_ file is also updated. The same way, if I uncomment the field and save again, after rebooting the field appears in the schema again.
That is what I understand as _hot-reloading_ and at least for me, that is enought in order to make easier the development process.
Regards.
It's full reload, with creating DB connection again, etc.
Hot reload is that our app react on changes, e.g. when we change the GraphQL field name, it reloads only the schema but the rest of the code (containers, connections, etc.) are not touched at all.
In frontend world:
OK. I understand. Thank you so much for share your point of view with me.
I match with your point of view if we talk about frontend, but I have a new question: if the schema is generated before the server start-up and someone wants to change the types definition, it's imperative to stop the server, compile the new structure and restart the server with the new schema definition, doesn't it? If this hypotesis is right, any change in the types definition couldn't be compiled and accepted by the server on the fly.
What do you think?
I have webpack working with hot reloading:
webpack.common.js
const path = require('path');
module.exports = {
module: {
rules: [
{
exclude: [path.resolve(__dirname, 'node_modules')],
test: /\.ts$/,
use: 'ts-loader'
},
{
exclude: /node_modules/,
loader: 'graphql-tag/loader',
test: /\.(graphql|gql)$/
}
]
},
output: {
filename: 'server.js',
path: path.resolve(__dirname, 'dist')
},
resolve: {
extensions: ['.ts', '.js', '.graphql']
},
target: 'node'
};
webpack.development.js
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const merge = require('webpack-merge');
const nodeExternals = require('webpack-node-externals');
const path = require('path');
const webpack = require('webpack');
const common = require('./webpack.common.js');
module.exports = merge.smart(common, {
devtool: 'inline-source-map',
entry: ['webpack/hot/poll?1000', path.join(__dirname, 'src/index.ts')],
externals: [
nodeExternals({
whitelist: ['webpack/hot/poll?1000']
})
],
mode: 'development',
plugins: [new CleanWebpackPlugin(), new webpack.HotModuleReplacementPlugin()],
watch: true
});
webpack.production.js
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const merge = require('webpack-merge');
const nodeExternals = require('webpack-node-externals');
const path = require('path');
const common = require('./webpack.common.js');
module.exports = merge(common, {
devtool: 'source-map',
entry: [path.join(__dirname, 'src/index.ts')],
externals: [nodeExternals({})],
mode: 'production',
plugins: [new CleanWebpackPlugin()]
});
"dev": "NODE_ENV=development npm run build",
"build": "webpack --config webpack.$NODE_ENV.js",
"start": "node dist/server",
index.js
import 'reflect-metadata';
import { ApolloServer, Config } from 'apollo-server';
import { buildSchema } from 'type-graphql';
import { Container } from 'typedi';
import { environment } from './environment';
async function main(): Promise<void> {
const schema = await buildSchema({
resolvers: [],
container: Container
});
// configure the server here
const serverConfig: Config = {
schema,
introspection: true,
playground: true
};
const server = new ApolloServer(serverConfig);
server
.listen(environment.port)
.then(({ url }) => console.log(`馃殌 Server ready at ${url}.`));
if (module.hot) {
module.hot.accept();
module.hot.dispose(() => server.stop());
}
}
main();
Hope this helps!
As #234 is now solved, this issue should be fixed too 馃帀
Please install [email protected] and let me now if the issue still happens 馃槈
Most helpful comment
I had the same issue as you were having (never bothered to run the production build yet). What happens is that Webpack in production mode mangles the class and functions names. Meaning that they are shortened to a single letter. In my case, this lead to naming conflicts. I would recommend reading this: https://webpack.js.org/plugins/terser-webpack-plugin/.