flow
flow copied to clipboard
Support to build frontend from TypeScript sources
In NPM mode JavaScript sources can be placed in META-INF/resources/frontend
to be picked up by the Maven plugin. Adding TypeScript support for this would be useful since it allows type-checking and decorators (and it's also adopted by LitElement).
Given that if you place TypeScript sources in the root frontend
folder and setup the ts-loader
in the Webpack config it works out of the box (see @marcushellberg vaadin-lit-typescript
), the same approach doesn't work for files in the META-INF/resources/frontend
of JAR dependencies.
Related issues: https://github.com/vaadin/flow/issues/6272 https://github.com/vaadin/flow/issues/6279 https://github.com/marcushellberg/vaadin-lit-typescript/issues/1
Steps I've tried:
- Create a component annotated with
@JsModule
:
@Tag("my-component")
@JsModule("./my-component/my-component.ts")
public class MyComponent extends Component {}
-
Place TypeScript source in
META-INF/resources/frontend/my-component/my-component.ts
-
Add the JAR dependency to a WAR
-
Add
typescript
andts-loader
topackage.json
and add TypeScript configuration towebpack.config.json
:
const merge = require('webpack-merge');
const flowDefaults = require('./webpack.generated.js');
module.exports = merge(flowDefaults, {
resolve: {
extensions: ['.ts', '.tsx', '.js', '.json']
},
devtool: 'inline-source-map',
module: {
rules: [{
// Include ts, tsx, js, and jsx files.
test: /\.tsx?$/,
exclude: /node_modules/,
loader: 'ts-loader',
}],
}
});
- Run the
build-frontend
mojo, which fails with
Failed to find the following imports in the `node_modules` tree:
- @vaadin/flow-frontend/my-component/my-component.ts
If the build fails, check that npm packages are installed.
This is because of the plugin only copying js
and css
files from JARs, so I've added **/*.ts
to WILDCARD_INCLUSIONS
in TaskCopyFrontendFiles
as suggested by @caalador and the file gets copied but then Webpack fails again:
ERROR in ../node_modules/@vaadin/flow-frontend/my-component/my-component.ts?babel-target=es6 8:0
Module parse failed: Unexpected character '@' (8:0)
which is strange, since it works for files copied from the root frontend
directory.
I've found another approach/workaround, which I find a satisfying DX: basically, put TypeScript sources in src/main/typescript
and set the output directory in tsconfig.json
to src/main/resources/META-INF/resource/frontend
.
The project will have the following structure:
.
├── src
│ ├── main
│ │ ├── java
│ │ │ └── it
│ │ │ └── axians
│ │ │ └── vaadin
│ │ │ └── components
│ │ │ └── applayout
│ │ │ └── AppLayout.java
│ │ ├── typescript
│ │ │ └── axians-app-layout
│ │ │ └── axians-app-layout.ts
│ │ └── resources
│ │ └── META-INF
│ │ └── resources
│ │ └── frontend
│ │ └── axians-app-layout
│ │ ├── axians-app-layout.d.ts
│ │ ├── axians-app-layout.js
│ │ └── axians-app-layout.js.map
│ └── test
│ ├── java
│ └── resources
├── tsconfig.json
├── package.json
└── pom.xml
and can be packaged and included as a dependency.
P.S. Not quite sure if it gets module dependencies, though 😕
To clarify, Vaadin 15 will have support for TypeScript for client driven views, but this issue can be kept around (for now) for having support for TS in the JS modules that have Java server side components.
What I would like to see here is that you can load dependencies as
@JsModule("./something")
and this would work regardless of whether the file is something.js
or something.ts
. This is how imports work in TS files also
Is this still a valid issue? There is a Vaadin add-on example implementation for Vaadin 23 using TypeScript here: https://github.com/vaadin/addon-starter-lit-flow
One limitation with TypeScript-Java components like this is that the methods exported with @ClientCallable
don't export any type information, which makes the TS usage unintuitive and should be at least documented.