Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using with Svelte-Kit, error: "The requested module does not provide an export name" #94

Closed
frederikhors opened this issue Apr 3, 2021 · 14 comments

Comments

@frederikhors
Copy link

Hi @timostamm! Your work is great! Really, I'm speechless! ❤️

i tried both v1 and v2 (now I'm on 2.0.0-alpha.17) and using https://vitejs.dev I get this error:

The requested module '/node_modules/.vite/@protobuf-ts_runtime.js?v=e308126a' does not provide an export named 'BinaryReadOptions'

and also for:

  • BinaryWriteOptions
  • IBinaryReader
  • IBinaryWriter
  • and so on...

If I open the generated files and change this:

import { ServiceType } from "@protobuf-ts/runtime-rpc";
import { BinaryWriteOptions } from "@protobuf-ts/runtime";
import { IBinaryWriter } from "@protobuf-ts/runtime";
import { WireType } from "@protobuf-ts/runtime";
import { BinaryReadOptions } from "@protobuf-ts/runtime";
import { IBinaryReader } from "@protobuf-ts/runtime";
import { UnknownFieldHandler } from "@protobuf-ts/runtime";
import { MessageType } from "@protobuf-ts/runtime";

to this:

import { ServiceType } from "@protobuf-ts/runtime-rpc";
import type { BinaryWriteOptions } from "@protobuf-ts/runtime";
import type { IBinaryWriter } from "@protobuf-ts/runtime";
import { WireType } from "@protobuf-ts/runtime";
import type { BinaryReadOptions } from "@protobuf-ts/runtime";
import type { IBinaryReader } from "@protobuf-ts/runtime";
import { UnknownFieldHandler } from "@protobuf-ts/runtime";
import { MessageType } from "@protobuf-ts/runtime";

(and in the other file too... ex: import type { RpcTransport } from "@protobuf-ts/runtime-rpc";)

it works!

Why?

How can I automagically fix this? With a .tsconfig option, maybe?

@timostamm
Copy link
Owner

Hi Frederik,

not sure what is going on - I can't reproduce, unfortunately:

I just created a simple app with npm init @vitejs/app with the react-ts template.

Then generated a simple message from msg-scalar.proto:

npx protoc -I . --ts_opt long_type_string --ts_out ./src msg-scalar.proto 

And use the message in App.tsx:

import {ScalarValuesMessage} from './msg-scalar';
console.log(
	ScalarValuesMessage.create()
);

npm run dev and npm run build work as expected, there are not compilation errors or warnings.

Vite 2.1.5, Typescript 4.2.3 got installed and tsconfig.json looks ok:

{
  "compilerOptions": {
    "target": "ESNext",
    "lib": ["DOM", "DOM.Iterable", "ESNext"],
    "types": ["vite/client"],
    "allowJs": false,
    "skipLibCheck": false,
    "esModuleInterop": false,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "ESNext",
    "moduleResolution": "Node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react"
  },
  "include": ["./src"]
}

This might be related to https://www.typescriptlang.org/tsconfig#importsNotUsedAsValues

It might be worth trying to set "importsNotUsedAsValues" : "remove" (the default behaviour) in a tsconfig.json for the generated code.

Do you have some more info so I can reproduce?

@frederikhors
Copy link
Author

frederikhors commented Apr 6, 2021

This is the repo: https://github.com/frederikhors/protobuf-ts-issue-94.

I used this cmd:

npx protoc -I .\src\routes\protobuf\ --ts_opt long_type_string --ts_out .\src\routes\protobuf\ ./src/routes/protobuf/msg-scalar.proto

I'm using Win 10 64, node v14.16.0, npm v7.8.0.

Steps:

  • clone it with git clone https://github.com/frederikhors/protobuf-ts-issue-94.git

  • npm install

  • npm run dev -- --open

  • click on "Protobuf" top menu link

  • this is the error on my Windows 10:

    image

  • the console.log() works but NOT in browser console: on node/PC console!

@timostamm
Copy link
Owner

I can reproduce, thanks.

The root cause seems to be a limitation of svelte's TypeScript preprocessor. It is not smart enough to figure out that an import of an interface for example can simply be omitted in Javascript. You have to explicitly use import type in svelte to import types. See this issue: sveltejs/svelte-preprocess#206

I am not sure whether I would consider this limitation acceptable. As a user, I don't want to think about whether I am using an import as a type or as a value.

For example, I have to use import type in this case:

import type {MyClass} from "./my-class";
let x: MyClass;

But not in this case:

import {MyClass} from "./my-class";
let x: MyClass = new MyClass();

The TypeScript compiler sorts this stuff out flawlessly by default. Maybe svelte should too.

There is an easy workaround:

npx protoc -I . --ts_opt long_type_string,force_optimize_code_size --ts_out ./src msg-scalar.proto 
                                          ^^^^^^^^^^^^^^^^^^^^^^^^

If you use the plugin parameter force_optimize_code_size, protobuf-ts will use reflection for the binary format. This results in much smaller code size (you probably want this in a web app), and by coincidence the code only uses value imports.

I am not sure if this works in all cases, but it certainly does work with msg-scalar.proto. Could you give this workaround a try? If you notice any problems, let me know.

@frederikhors
Copy link
Author

I opened sveltejs/svelte-preprocess#340.

Thank for your precious answer.

I don't like workarounds. And I know this is not your fault!

But I'm worried for two reasons:

  • today I could solve it like this, but what if something changes tomorrow?

  • are we sure that optimization for CODE_SIZE is better for web apps? I mean, apart from the gain on the size of the final bundle to download, does the speed in operations suffer? Do we have benchmarks in this regard?

Thanks again for all your work.

@frederikhors
Copy link
Author

Small note: I'm trying with the force_optimize_code_size option and anyway the *.client.ts files have that problem.

So not even in this way I can solve.

@frederikhors frederikhors changed the title Using with Vite, error: "The requested module does not provide an export name" Using with Svelte-Kit, error: "The requested module does not provide an export name" Apr 6, 2021
@timostamm
Copy link
Owner

are we sure that optimization for CODE_SIZE is better for web apps? I mean, apart from the gain on the size of the final bundle to download, does the speed in operations suffer? Do we have benchmarks in this regard?

Yes, see packages/benchmarks/perf.ts

The difference in speed is surprisingly negligible.

### read binary
google-protobuf             : 12.33 ops/s
ts-proto                    : 22.69 ops/s
protobuf-ts (speed)         : 25.07 ops/s
protobuf-ts (speed, bigint) : 25.54 ops/s
protobuf-ts (size)          : 22.68 ops/s
protobuf-ts (size, bigint)  : 23.12 ops/s
### write binary
google-protobuf             : 14.25 ops/s
ts-proto                    : 10.7 ops/s
protobuf-ts (speed)         : 11.9 ops/s
protobuf-ts (speed, bigint) : 11.63 ops/s
protobuf-ts (size)          : 10.64 ops/s
protobuf-ts (size, bigint)  : 10.95 ops/s
### from partial
ts-proto                    : 36.7 ops/s
protobuf-ts (speed)         : 27.75 ops/s
protobuf-ts (size)          : 27.57 ops/s
### read json
ts-proto                    : 35.96 ops/s
protobuf-ts (speed)         : 15.92 ops/s
protobuf-ts (size)          : 17.38 ops/s
### write json
ts-proto                    : 139.48 ops/s
protobuf-ts (speed)         : 29.2 ops/s
protobuf-ts (size)          : 28.36 ops/s
### read json string
ts-proto                    : 14.14 ops/s
protobuf-ts (speed)         : 8.79 ops/s
protobuf-ts (size)          : 8.84 ops/s
### write json string
ts-proto                    : 19.28 ops/s
protobuf-ts (speed)         : 18.49 ops/s
protobuf-ts (size)          : 18.91 ops/s

@frederikhors
Copy link
Author

Why is ts-proto faster?

@timostamm
Copy link
Owner

Why is ts-proto faster?

This is a microbenchmark, take it with a grain of salt 🙄

protobuf-ts is way more strict in JSON I/O than ts-proto and this costs some cycles. Note that you probably want to work with JSON strings, where most of the difference disappears. Also, you probably don't even want to use JSON, but the binary format.

@timostamm
Copy link
Owner

Small note: I'm trying with the force_optimize_code_size option and anyway the *.client.ts files have that problem.

Version 2.0.0-alpha.18 was just published. This should generate import type where necessary.

It is very likely that there are some edge cases that don't work yet. Just let me know when you notice something missing.

Cheers!

@frederikhors
Copy link
Author

frederikhors commented Apr 6, 2021

Did you published it with latest tag?

UPDATE:

I'm asking it because npm-check cannot detect it.

image

@frederikhors
Copy link
Author

I tried 2.0.0-alpha.18 and with my files it works amazingly well!

@timostamm
Copy link
Owner

Did you published it with latest tag?

Thanks for the heads up, that was not intentional. 🔥 🚒

I could not unpublish in time. v1.0.13 fixes the "latest" channel,
v2.0.0-alpha.19 adds type imports to grpc clients in the "next" channel.

@sandalsoft
Copy link

"You have to explicitly use import type in svelte to import types."

Thank you @timostamm !!

For anyone else who came here from a Google search import type { MyType} from "$types"; fixed this.

I ran into this problem tonight, and I'm on:
svelte - v3.42.5
@sveltejs/kit - v1.0.0-next.166
@sveltejs/vite-plugin-svelte - v1.0.0-next.24

@timostamm
Copy link
Owner

BTW, svelte apparently fixed this in v4.9.0, see sveltejs/svelte-preprocess#392

timostamm added a commit that referenced this issue Apr 6, 2022
We were generating `import * as grpc from "@grpc/grpc-js";` were we should have been generating `import type * as grpc from "@grpc/grpc-js";`. See #94.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants