Skip to content
This repository was archived by the owner on Aug 7, 2021. It is now read-only.

Cannot use const enums from plugins #1012

Closed
1 task
PeterStaev opened this issue Aug 4, 2019 · 7 comments
Closed
1 task

Cannot use const enums from plugins #1012

PeterStaev opened this issue Aug 4, 2019 · 7 comments
Assignees
Labels
docs migration-to-bundle The issue is describing a breaking change in the Bundle workflow compared to the Legacy one.

Comments

@PeterStaev
Copy link
Contributor

Environment
Provide version numbers for the following components (information can be retrieved by running tns info in your project folder or by inspecting the package.json of the project):

  • CLI: 6.0.0

  • Cross-platform modules: 6.0.0

  • Android Runtime:6.0.0

  • iOS Runtime:6.0.0

  • Plugin(s):

  • Node.js: 10.16.0

  • Please, attach your package.json and webpack.config.js as these configurations are usually critical for investigating issues with webpack

Describe the bug
Previously it was possible to have an exported const enum defined in a plugin's .d.ts and then use its values in the app. With the new web pack only workflow and new version of the web pack plugin this is no longer possible.

To Reproduce

Expected behavior
Users should be able to use const enums defined in the .d.ts files of plugins/npm packages.

Sample project
const-enum-imports.zip
Tried both with export const and declare const in the .d.ts but neither are working.

Additional context

@PeterStaev PeterStaev changed the title Cannot use const enums demo plugins Cannot use const enums from plugins Aug 4, 2019
@DimitarTachev
Copy link
Contributor

Hi @PeterStaev,

We've missed documenting this case. When exposing a const enum from a plugin, you have to define it in a .ts file (without the declare keyword) and enable the preserveConstEnums option in your tsconfig.

In other words, in the attached example, you need the following files:
./test-plugin/test-plugin.ts:

export const enum IntEnum {
    X,
    Y,
    Z
}

export const enum StringEnum {
    X = "x",
    Y = "y",
    Z = "z",
}

export function test() {
    return "this is a test";
}

./test-plugin/tsconfig.json:

{
    "compilerOptions": {
        ...
        "preserveConstEnums": true,
    }
    ...
}

@KristianDD KristianDD added docs migration-to-bundle The issue is describing a breaking change in the Bundle workflow compared to the Legacy one. labels Aug 5, 2019
@PeterStaev
Copy link
Contributor Author

@DimitarTachev , how will this work in an actual plugin published on NPM? For example here: https://github.com/PeterStaev/nativescript-telerik-reporting/tree/master/reporting/document I have a TS file that during compile of the plugin is transpiled to JS and this is what is included in the plugin package. Then I have a .d.ts that is included as typing info. If I don't transpile the code to JS, then how would the plugin be used form Nativescript Core JS flavor?

Also as far as I understand that compile option should be set for the app and not the plugin, right?

@DimitarTachev
Copy link
Contributor

@PeterStaev,

When you set the preserveConstEnums property, the enums will be included in the generated JavaScript files. In other words, you just need to publish a plugin version which is transpiled with the above-mentioned configuration.

P.S. You could also keep the enum declarations in the d.ts files.

@PeterStaev
Copy link
Contributor Author

@DimitarTachev , I've just tried your solution, but this is far from ideal. Adding this compile option, makes the const enum work just like a normal enum, i.e. it gets a "class" created within the JS file of the plugin. Not only that, but then in the code using the plugin the members are not replaced with the constant value, but instead are using the generated class...

So you might as well say in the docs that const enums are not supported in plugins, since using what you suggested makes const enums behave not like const enums 😞

@DimitarTachev
Copy link
Contributor

@PeterStaev

Developing a plugin, you have to ensure that your const enums could be used both from the .d.ts file and from the .js file. Based on the selected flavor, the end-users could decide if they will inline the enums from the .d.ts files or use the classes from the js files.

I suppose that if you do not emit the enum classes in the JS files, your plugin cannot be used in NativeScript Core JS flavor even with NativeScript 5.4. Did your setup work properly in this flavor before NativeScript 6.0?

The only difference in NativeScript 6.0 should be in the NativeScript Core TS flavor. As recommended by the ts-loader for much faster builds and required by the ts-loader for HMR builds, we've switched the transpileOnly option of the ts-loader to true which leads to the const enums behavior change.

As far as I know, the const enums are still inlined by default in Angular apps and the users are able to enable them in NativeScript Core TS apps by disabling the transpileOnly flag in their webpack.config but as I already said, that's the faster and recommended approach by the ts-loader and they will also have some hmr issues.

If you want to optimize the enum calls in your plugin and inline them, you could execute multiple TypeScript compilations and have both inlined enums and generated enum classes in the JS files but I don't believe it worth it.

@PeterStaev
Copy link
Contributor Author

@DimitarTachev , the plugin was working fine prior to 6.0 in both webpacked and non-webpacked apps.

For people using Core JS flavor, they would have to type the string themselves, instead of using the enum. But for people using TS they would be able to use the intellisense of the const enum in the .d.ts and yet, when the file transpiled to JS it would be replaced with the respective string, thus eliminating the additional code.

I could use a specific type for this (i.e. declare type DocumentType = "PDF" | "HTML5" |....) but then TS users will still have to type in the string instead of using the intellisense.

@DimitarTachev
Copy link
Contributor

@PeterStaev

Thanks for the additional details.

I'm closing this issue because as I've already said, this limitation is caused by the ts-loader and even before NativeScript 6.0 the ts-loader was configured in transpileOnly mode when running the apps with hmr. You could take a look at the configuration of nativescript-dev-webpack@0.22.0 - https://github.com/NativeScript/nativescript-dev-webpack/blob/0.22.0/templates/webpack.typescript.js#L214.

Also, even before the 0.22 version of the Webpack plugin and the official HMR support in NativeScript, the end-users were able to change this setting in their webpack.config for performance improvements and I don't see any breaking changes for const enums in the plugin development in NativeScript 6.0. We've just changed our recommendations for the transpileOnly value by changing the default value for the TypeScript apps.

@DimitarTachev DimitarTachev self-assigned this Aug 8, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
docs migration-to-bundle The issue is describing a breaking change in the Bundle workflow compared to the Legacy one.
Projects
None yet
Development

No branches or pull requests

3 participants