Webpack Encore typescript livereload weird behavior
Video example
Sorry for low quality, its best I could do
Package version
"@adonisjs/core": "^5.8.4",
"@adonisjs/repl": "^3.1.11",
"@adonisjs/view": "^6.1.6",
"@symfony/webpack-encore": "^3.0.0",
Node.js and npm version
node v16.15.1, npm 8.11.0
Sample Code (to reproduce the issue)
I have followed the tutorial to configure views and Webpack Encore. This only happens when typescript files are modified. Changing templates or css works as expected. The only change in the webpack config is
Encore.addEntry('app', './resources/js/app.js')
to
Encore.addEntry('app', './resources/js/app.ts').enableTypeScriptLoader();
The resource is included in layout with @entryPointScripts('app').
I need to enable typescript in my app, and I think this is a common use-case. I am not sure if this is encore or integration issue, but I feel that it is important to report this behavior for the latest build of adonisjs.
Thank you so much for this framework! The docs are amazing, cant wait to rewrite my backend 😁
The issue report was for Chromium. When using Firefox, the browser does not refresh and is stuck on "Unable to connect". It looks like the browser is refreshed before Encore's typescript compiler has time to rebuild the frontend code. In dev-tools I see failing request to http://localhost:3333/ with no reponse.
Hey @romanzy-1612! 👋🏻
Could you please paste the content of your .adonisjsrc.json file?
Your Adonis server is restarting whenever you change one of your frontend files. This can be configured inside the metaFiles properties in .adonisjsrc.json.
I think the server is restarting because the frontend codebase is in TypeScript and the same tsconfig.json is used for both the backend and the frontend. Thefore, when AdonisJS watcher asks TypeScript for the files to watch, it is getting frontend files as well.
I think, the frontend tsconfig has to be separate and then you should ignore the frontend files inside the backend tsconfig.json file.
When ace generates webpack config, the following options toward the end:
options.liveReload = true;
options.static.push({
directory: join(__dirname, './resources/views'),
watch: true,
});
Here is the .adonisjsrc.json
{
"typescript": true,
"commands": [
"./commands",
"@adonisjs/core/build/commands/index.js",
"@adonisjs/repl/build/commands",
"@adonisjs/lucid/build/commands"
],
"exceptionHandlerNamespace": "App/Exceptions/Handler",
"aliases": {
"App": "app",
"Config": "config",
"Database": "database",
"Contracts": "contracts"
},
"preloads": ["./start/routes", "./start/kernel"],
"providers": [
"./providers/AppProvider",
"@adonisjs/core",
"@adonisjs/view",
"@adonisjs/lucid"
],
"aceProviders": ["@adonisjs/repl"],
"tests": {
"suites": [
{
"name": "functional",
"files": ["tests/functional/**/*.spec(.ts|.js)"],
"timeout": 60000
}
]
},
"testProviders": ["@japa/preset-adonis/TestsProvider"],
"metaFiles": [
{
"pattern": "resources/views/**/*.edge",
"reloadServer": false
}
]
}
The default configurations really makes sense and look correct. I have tried many different combinations of these two configs. Also I've tried specifying config file in ts-loader, and so much more.
What would be the most optimal way of structuring a typescript client "sub-application"? Where to put it, how to enable typescript? It would be nice to have this all organized by ace.
I currently have my client app in /resources/frontend, and I use a single package.json at the root of the server. It is not ideal, but it allows sharing of types and schemas, which is another pain in ts project structuring.
Ive created a repo demonstrating this behavior and my attempts at configuring sharing of code/types between server and client. You can find it here
Console output when reloading:
UPDATE: resources/frontend/src/app.ts
[ info ] re-starting http server...
[ encore ] WAIT Compiling...4:37:33 PM
UPDATE: public/assets/manifest.json
[ encore ] DONE Compiled successfully in 101ms4:37:33 PM
[ encore ] webpack compiled successfully
[1657975053642] INFO (hello-world-web/31505 on ____): started server on 0.0.0.0:3333
I will keep experimenting on it. Once this issue is resolved, Webpack Encore typescript support should be added to the docs. Also guides on how to structure sub-applications would be appreciated. Also it would be nice for ace to scaffold this automatically. I would like to help to make this happen.
Thanks!
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
I think the server is restarting because the frontend codebase is in TypeScript and the same
tsconfig.jsonis used for both the backend and the frontend. Thefore, when AdonisJS watcher asks TypeScript for the files to watch, it is getting frontend files as well.I think, the frontend tsconfig has to be separate and then you should ignore the frontend files inside the backend
tsconfig.jsonfile.
I was having this issue and I think I've solved it just as you described it here.
I've created a new TypeScript config at resources/js/tsconfig.json containing:
{
"extends": "adonis-preset-ts/tsconfig.json",
"include": ["**/*"],
"compilerOptions": {
"outDir": "build",
"rootDir": "./",
"sourceMap": true
}
}
And then modified the root tsconfig.json adding the resources directory to the exlcudes key, so it looks like:
...
"exclude": ["node_modules", "build", "resources"],
...
So far all seems to work as expected. Typescript frontend files are live reloaded without a server restart and the backend restarts when backend files are changed. I'm not sharing types, etc between frontend and backend yet, so not sure if that would be a problem.
EDIT:
I've also had to create a new eslint config file at resources/js/.eslintrc.js containing:
export default {
parserOptions: {
project: './tsconfig.json',
},
}