core icon indicating copy to clipboard operation
core copied to clipboard

Webpack Encore typescript livereload weird behavior

Open romanzy313 opened this issue 3 years ago • 6 comments

Video example

simplescreenrecorder-2022-07-15_01 48 46 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 😁

romanzy313 avatar Jul 14 '22 22:07 romanzy313

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.

romanzy313 avatar Jul 15 '22 00:07 romanzy313

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.

RomainLanz avatar Jul 15 '22 06:07 RomainLanz

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.

thetutlage avatar Jul 15 '22 07:07 thetutlage

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. 

romanzy313 avatar Jul 15 '22 22:07 romanzy313

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!

romanzy313 avatar Jul 16 '22 13:07 romanzy313

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.

stale[bot] avatar Sep 16 '22 02:09 stale[bot]

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.

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',
  },
}

msurdi avatar Oct 08 '22 06:10 msurdi