wasm-tool / parcel-plugin-wasm.rs

wasm-bindgen support for Parcel bundler
MIT License
66 stars 16 forks source link

"Cannot find module" from .ts file. #26

Open rbtcollins opened 5 years ago

rbtcollins commented 5 years ago

I'm not sure whats going on here - rather new to parcel. I have a wasm project in a parallel direction to the js tree:

npm-project
+src
 |+foo.ts
wasm-project
+Cargo.toml

in foo.ts I have tried each of

import lib from "../wasm-project/Cargo.toml";
import lib from "../../wasm-project/Cargo.toml";
import lib from "../../../wasm-project/Cargo.toml";

all of them report 'Cannot find module'.

The npm project using parcel is an existing mature code base that works fine in other regards as far as I can tell :).

Any suggestions? Is this a supported feature?

catsigma commented 5 years ago

Your folder is:

npm-project
  +src
    +foo.ts
wasm-project
  +Cargo.toml

right?

And what cmd did you use to complie the foo.ts?

rbtcollins commented 5 years ago

Yes, thats right.

Compiled the typescript via > tsc -p . - the build does a

npm run compile && npm run bundle:browser && npm run bundle:node

then

tsc -p .

Which is when the error from typescript occurs.

I've attempted to work around this using a js thunk file - I copied the .d.ts from the rust pkg directory to 'src/wasmthunk.d.ts' and made a 'wasmthunk.js' that imports from the Cargo.toml and then exports everything.

That sort of worked.

I say sort of worked because its throwing an error in the browser:

TypeError: s.readFile is not a function wasm-loader.js:437

which is from

    function E(r) {
      const s = require("fs");

      return new Promise(function (e, n) {
        s.readFile(t + r, function (t, r) {
          t ? n(t) : e(r.buffer);
        });
      }).then(e => WebAssembly.instantiate(e, {
        "./foo_wasm": n
...

Thank you for responding so amazingly fast btw!

rbtcollins commented 5 years ago

Re the workaround failing, we bundle twice: once for browser and once for node:

parcel build -d browser --out-file browser.js --global foo src/index.ts

and

parcel build --target node src/index.ts

Then we call parcel serve -d out path-to-index.html

catsigma commented 5 years ago

In my own test project, I can directly use parcel to build a .ts file with Cargo.toml import.

jamieparkinson commented 5 years ago

I encountered a similar sort of thing to this - I believe that the reason that parcel can build the .ts file importing a Cargo module with this plugin is because Parcel is not actually performing proper TS checking & module resolution (see here for example).

To "prove" this you can move the definition generated by wasm-pack, /pkg/<module name>.d.ts, to Cargo.toml.d.ts and you should see that TS is happy with this (although it lacks the default wasm export, which is typed in /pkg/<module_name>_bg.d.ts).

I think that one option for this would be to merge the generated definitions into this.wasm_bindgen_js in the Asset class, or (probably better) to merge them into a new Cargo.toml.d.ts file, like what's done here for CSS Modules.

This merging & string-twiddling does seem brittle to me so perhaps it would be better to export the raw wasm stuff separately, like the Webpack loader does. Hopefully the situation will improve when Parcel's TS support is better!

sliminality commented 4 years ago

I'm having the same problem, it's a huge headache. This issue is also related: https://github.com/rustwasm/wasm-bindgen/issues/182#issuecomment-678066039

chinoto commented 3 years ago

I've spent a couple days trying to figure this out and settled on ln -s ./pkg/{package_name}.d.ts Cargo.toml.d.ts. Slightly better than copying since it only has to be done once and works forever instead of needing to be included in a build script. partially due to being new to TypeScript and not understanding how .d.ts files are handled right away.

npx parcel build Cargo.toml works, so I could potentially import * as my_tool from './my_tool/pkg' in index.html and run npx parcel <build|watch|serve> my_tool/Cargo.toml index.html assuming they are built in that order and not concurrently.

chinoto commented 3 years ago

I've found a partial workaround for this: ln -s pkg/{package_name}.d.ts Cargo.toml.d.ts. The next time you run parcel, the typing file in pkg will be created and the symbolic link will make your import of Cargo.toml properly typed. Slightly better than copying because there's no need to hook into Parcel's build process to make sure a copy happens. Would be nice if you could tell TypeScript "treat importing this file as if I imported this other file that is fully typed". You don't get typings for {package_name}_bg.wasm.d.ts, not sure how to get around this, though it shouldn't usually matter.