webpack plugin for Rust

Overview

@wasm-tool/wasm-pack-plugin

webpack plugin for Rust

Installation

With npm:

npm install --save-dev @wasm-tool/wasm-pack-plugin

Or with Yarn:

yarn add --dev @wasm-tool/wasm-pack-plugin

wasm-pack

We expect wasm-pack to be in your $PATH. See installation here.

The minimum required wasm-pack version is 0.8.0

Linting

This project uses the prettier with default configuration. Fo manually format the code run the lint:fix script.

Usage

Add the loader in your webpack.config.js:

const path = require('path')
const WasmPackPlugin = require('@wasm-tool/wasm-pack-plugin')

module.exports = {
    // ...

    plugins: [
        new WasmPackPlugin({
            crateDirectory: path.resolve(__dirname, 'crate'),

            // Check https://rustwasm.github.io/wasm-pack/book/commands/build.html for
            // the available set of arguments.
            //
            // Optional space delimited arguments to appear before the wasm-pack
            // command. Default arguments are `--verbose`.
            args: '--log-level warn',
            // Default arguments are `--typescript --target browser --mode normal`.
            extraArgs: '--no-typescript',

            // Optional array of absolute paths to directories, changes to which
            // will trigger the build.
            // watchDirectories: [
            //   path.resolve(__dirname, "another-crate/src")
            // ],

            // The same as the `--out-dir` option for `wasm-pack`
            // outDir: "pkg",

            // The same as the `--out-name` option for `wasm-pack`
            // outName: "index",

            // If defined, `forceWatch` will force activate/deactivate watch mode for
            // `.rs` files.
            //
            // The default (not set) aligns watch mode for `.rs` files to Webpack's
            // watch mode.
            // forceWatch: true,

            // If defined, `forceMode` will force the compilation mode for `wasm-pack`
            //
            // Possible values are `development` and `production`.
            //
            // the mode `development` makes `wasm-pack` build in `debug` mode.
            // the mode `production` makes `wasm-pack` build in `release` mode.
            // forceMode: "development",

            // Controls plugin output verbosity, either 'info' or 'error'.
            // Defaults to 'info'.
            // pluginLogLevel: 'info'
        }),
    ],

    // ...
}

and then import your pkg folder from wasm-pack:

import('./path/to/your/pkg').then((module) => {
    module.run()
})
Comments
  • Various quality of life improvements.

    Various quality of life improvements.

    Here is a list of changes in this PR:

    • Adding in outDir and outName options.

    • It now watches Cargo.toml for changes.

    • It fixes Webpack erroring about pkg/index.js if wasm-pack errors.

    • Changing to use Webpack's error system, which causes Webpack compilation to gracefully stop if there is an error.

    The end result is a much nicer experience for the end user:

    • It no longer spews out a lot of useless Webpack information when compilation fails.

    • It works perfectly in watch mode, with full auto-reloading, even in the case that there are errors in the Rust code.

    • The user can now edit Cargo.toml and it will auto-rebuild.

    However, this is a BREAKING CHANGE, because it now defaults --out-dir to pkg, and defaults --out-name to index. This is necessary in order to fix a Webpack error. Therefore, this will need a major version bump.

    opened by Pauan 17
  • Configurable watch list

    Configurable watch list

    Problem: Currently the watcher is set up to monitor only the main crate's src/ directory and in case you're working on a few interdependent packages at the same time, there's no way to trigger build on changes to any of the secondary crates.

    Solution: Allow customizing the directory watch list.

    opened by heilhead 9
  • WASM breaks after passing through webpack

    WASM breaks after passing through webpack

    While the WASM coming out of wasm-pack is valid, what comes out of webpack using wasm-pack-plugin doesn't seem to be valid WASM. It can't be run in the browser and it can't be parsed by wasm2wat.

    opened by LaylBongers 7
  • fix: Watch mode for Rust files

    fix: Watch mode for Rust files

    This will check for watch instead of watchMode since watchMode isn't a valid configuration. This will resolve this issue: https://github.com/rustwasm/rust-webpack-template/issues/69.

    opened by drager 5
  • add withTypescript option

    add withTypescript option

    Add a withTypescript option to optionally generate d.ts files for the wasm module in order to integrate with typescript.

    Example tsconfig.json

    {
        "compilerOptions": {
            "module": "esnext", // needed to have dynamic imports
            "lib": [
                "dom",
                "es2015"
            ]
        },
        "files": [
            "./index.ts"
        ]
    }
    

    Example webpack.config.json

    const path = require("path");
    const HtmlWebpackPlugin = require("html-webpack-plugin");
    const WasmPackPlugin = require("@wasm-tool/wasm-pack-plugin");
    
    module.exports = {
      entry: "./index.ts",
      output: {
        path: path.resolve(__dirname, "dist"),
        filename: "bundle.js"
      },
      plugins: [
        new HtmlWebpackPlugin(),
    
        new WasmPackPlugin({
          crateDirectory: path.resolve(__dirname, "."),
          withTypeScript: true
        }),
      ],
      resolve: {
        extensions: [".ts", ".tsx", ".js", ".wasm"]
      },
      module: {
        rules: [{
          test: /\.tsx?$/,
          loader: "ts-loader"
        }]
      }
    };
    
    

    Example index.ts

    import("./pkg/wasm_pack_test").then(module => {
      module.run();
    });
    
    
    opened by d-dorazio 5
  • WasmPackPlugin running multiple builds in parallel?

    WasmPackPlugin running multiple builds in parallel?

    Hi! I don't know if this is a bug in wasm-pack-plugin or in webpack, but I could really use help, so I'm asking here. I've checked the existing issues and I'm surprised that I don't seem to see other mentions of it.

    It seems like either webpack is kicking off multiple parallel runs of wasm-pack-plugin, where it should only start 1, or possibly that wasm-pack-plugin has multiple callbacks running in parallel where only 1 is intended. The number of parallel filesystem watching jobs seems to stack up non-deterministically as I work, I've gotten up to maybe 9 of them at times.

    I've experienced this issue in multiple projects with multiple very different setups, but it is currently happening to me with webpack 5 running under nextjs. It's happened to me before with very basic (no nextjs) webpack setups with webpack 4 too.

    If it's helpful I can put together a small example to reproduce it (I'm kind of hoping this is a known webpack issue that I can work around somehow).

    Sometimes the only impact is that builds take longer, or the browser can't refresh, but sometimes it causes errors to be erroneously reported, breaking browser refresh, sometimes because wasm-opt stomps on itself during filesystem operations, other times the files in wasm-pack's output directory are mangled.

    Here's some example console output:

        Finished release [optimized + debuginfo] target(s) in 7.83s
    [INFO]: Optimizing wasm binaries with `wasm-opt`...
    [INFO]: Optimizing wasm binaries with `wasm-opt`...
    Error: No such file or directory (os error 2)
    To disable `wasm-opt`, add `wasm-opt = false` to your package metadata in your `Cargo.toml`.
    [INFO]: ✨   Done in 42.88s
    [INFO]: đŸ“Ļ   Your wasm pkg is ready to publish at /Users/rch/repo/app/web/public/pkg.
    ✅  Your crate has been correctly compiled
    
    ℹī¸  Compiling your crate in release mode...
    
    ℹī¸  Compiling your crate in release mode...
    
    [INFO]: đŸŽ¯  Checking for the Wasm target...
    [INFO]: đŸŽ¯  Checking for the Wasm target...
    [INFO]: 🌀  Compiling to Wasm...
    [INFO]: 🌀  Compiling to Wasm...
       Compiling app v0.0.0 (/Users/rch/repo/app/app)
    warning: `app` (lib) generated 3 warnings
        Finished release [optimized + debuginfo] target(s) in 7.50s
    [INFO]: Optimizing wasm binaries with `wasm-opt`...
    [INFO]: Optimizing wasm binaries with `wasm-opt`...
    Error: No such file or directory (os error 2)
    To disable `wasm-opt`, add `wasm-opt = false` to your package metadata in your `Cargo.toml`.
    [INFO]: ✨   Done in 43.15s
    [INFO]: đŸ“Ļ   Your wasm pkg is ready to publish at /Users/rch/repo/app/web/public/pkg.
    

    Thanks! I really appreciate the code and work of this community. Let me know if I can add any clarity here.

    opened by robert-chiniquy 4
  • [feature] expose plugin logging configuration

    [feature] expose plugin logging configuration

    Allow wasm-pack-plugin's output level to controlled via a new configuration, pluginLogLevel. Valid values are 'info' (the default) or 'error'. The former maintains the status quo and the latter only reports serious errors.

    The rationale for this change is that Webpack itself can be quite verbose, to a fault even. Once the scaffolding for a wasm-pack-plugin based project is up and running smoothly, the additional plugin's informational messaging is less useful in combination with Webpack's logging. This gives clients a choice in how much to log and where.

    fix #83

    opened by niedzielski 4
  • wasm-pack cannot be launched

    wasm-pack cannot be launched

    When including the plugin like this:

    module.exports.plugins.push(new WasmPackPlugin({
          crateDirectory: Path.resolve(__dirname, "crate"),
        }));
    

    It always fails with:

    wasm-pack error: Error: spawn wasm-pack ENOENT
    

    Even though I have wasm-pack in $PATH and can launch it from the command line. I can even launch it right before adding the plugin like this:

    childProcess.spawn("wasm-pack", {stdio: [process.stdin, process.stdout, process.stderr]});
    

    what could be wrong?

    question 
    opened by fdietze 4
  • added error listener

    added error listener

    This is a 1-line change to avoid errors like this:

    image

    Since this is a very small change I didn't bump the version number in case you wanted to include this in a larger release.

    opened by liamcurry 4
  • Manually configure build mode (debug/release)

    Manually configure build mode (debug/release)

    I would like to be able to select within the webpack build script if wasm-pack is called with release/production or debug/development mode. Currently, this is done via webpack's mode configuration.

    Background: I develop a tiny webapp where the computation-heavy task is written in rust. In release mode, a task takes 500ms, while in debug mode 20s. This difference is fine to me, but when developing the non-rust parts I would like to develop using webpack's develop mode but still use the release version of the rust package to avoid long waits.

    If desired, I can create a PR to add a configuration option to this plugin.

    enhancement 
    opened by samuelpilz 4
  • Use wasm pack build

    Use wasm pack build

    should solve https://github.com/wasm-tool/wasm-pack-plugin/issues/27

    The diff is a bit noisy because I took the freedom to update some dependencies and to format the code a bit but the relevant commit is the last one. I can revert the other commits if they're out of scope.

    opened by d-dorazio 4
  •  Can't import the named export (imported as 'wasm')

    Can't import the named export (imported as 'wasm')

    Hi! I used wasm-pack build command and I'm getting the following error:

    ERROR in ./src/wasm-lib/pkg/index_bg.js 15:14-29
    

    wasm-pack-plugin: Can't import the named export (imported as 'wasm') from default-exporting module (only default export is available)

    The ./src/wasm-lib/pkg/index_bg.js file is auto-generated and looks like this:

    import * as wasm from './wasm_lib_bg.wasm';
    
    /**
    * @param {number} left
    * @param {number} right
    * @returns {number}
    */
    export function sort_array(left, right) {
        const ret = wasm.sort_array(left, right);
        return ret >>> 0;
    }
    

    I also added the syncWebAssembly flag to my Webpack config.

    opened by bart-krakowski 0
  • feat: add stdio & stderr output to npm and yarn

    feat: add stdio & stderr output to npm and yarn

    Add stdio and stderr output to NPM and Yarn processs, when they go to globally install wasm-pack.

    Add an error message if installing wasm-pack globally fails.

    Resolves #138

    opened by JosephLenton 2
  • Source maps?

    Source maps?

    It would be great to have source map support. This would involve generating a sourcemap (preferably including sources) from llvm dwarfdump info via this cli tool, or via wasm-pack (rustwasm/wasm-pack#824), and then adding this sourcemap to the build output and a reference in the wasm binary (see this).

    opened by leonhma 0
  • Typescript and Webpack 5 issues.

    Typescript and Webpack 5 issues.

    In a normal javascript project, I am able to use Webpack 5 and the wasm-pack-plugin just fine. You can see this working in this Rust Webpack sandbox, just open a new terminal and type yarn up.

    However in this Rust Webpack + Typescript sandbox (again use a new terminal to run yarn up as described in the README), I immediately get the following error with syncWebAssembly: true.

    ERROR in ./pkg/index_bg.wasm
    WebAssembly module is included in initial chunk.
    This is not allowed, because WebAssembly download and compilation must happen asynchronous.
    Add an async split point (i. e. import()) somewhere between your entrypoint and the WebAssembly module:
    * ./src/index.ts --> ./pkg/index.js --> ./pkg/index_bg.wasm
    * ... --> ./pkg/index.js --> ./pkg/index_bg.js --> ./pkg/index_bg.wasm
    * ... --> ./pkg/index_bg.js --> ./pkg/index_bg.js --> ./pkg/index_bg.wasm
    * ... --> ./src/index.ts --> ./src/index.ts --> ./pkg/index.js --> ./pkg/index_bg.wasm
    * ... --> ./pkg/index.js --> ./pkg/index_bg.wasm --> ./pkg/index_bg.js --> ./pkg/index_bg.wasm
    * ... --> ./pkg/index_bg.js --> ./pkg/index_bg.wasm --> ./pkg/index_bg.js --> ./pkg/index_bg.wasm
     @ ./pkg/index.js 1:0-40
     @ ./src/index.ts 25:55-78
    

    This is odd to me because I use import("../pkg/index") so not sure why this error would be thrown.

    When I update to use asyncWebAssembly: true instead, it compiles however the following does not display anything to the screen. Locally, there are a bunch of errors in the console about hello() being undefined.

    const rust = import("../pkg/index");
    
    rust.then((m) => {
      console.log(m);
      document.body.innerHTML = `
      <h1>Message from Rust:</h1>
        <h2>${m.hello()}</h2>
      `;
    });
    

    When checking the console, we can see that m is a promise not the rust module. (Apologies for the webpack errors I could not clear)

    Screen Shot 2022-09-11 at 8 33 27 PM

    Taking this into account I can get this working by using the normal ES6 import and just assuming it is a promise. However as you can shown VSCode sees this as an error. Screen Shot 2022-09-11 at 8 40 34 PM

    Property 'then' does not exist on type 'typeof import("blah/blah/blah")' .ts(2339)
    

    This looks different than the esm-integration proposal which I gather is what asyncWebAssembly is based on. To the best of my googling ability, I have not been able to find anything that looks similar.

    Questions

    • Why does this only happen with typescript?
    • Does wasm-pack-plugin need to be updated for asyncWebAssembly?
    • Should I take this up with webpack?
    opened by CarterFendley 0
  • (0 , _pkg__WEBPACK_IMPORTED_MODULE_0__. my_wasm_function) is not a function

    (0 , _pkg__WEBPACK_IMPORTED_MODULE_0__. my_wasm_function) is not a function

    Version: 1.6.0

    I started using this plugin and can't call WASM anymore.

    webpack config:

    const WasmPackPlugin = require("@wasm-tool/wasm-pack-plugin");
    // ...
    config.plugins = [
    ...config.plugins,
    new WasmPackPlugin({
        crateDirectory: path.resolve(__dirname, "../wasm-build"),
        outDir: path.resolve(__dirname, "src/pkg"),
    }),
    ];
    

    The browser shows "ERROR Rust compilation" and the console shows this:

    (0 , _pkg__WEBPACK_IMPORTED_MODULE_0__.my_wasm_function) is not a function
    

    In the previous working implementation I was using wasm like this:

    package.json dependency:

    "wasm": "file:../wasm-build",
    

    And then in the JS files:

    const wasmPromise = import("wasm");
    const { my_wasm_function } = await wasmPromise;
    

    The reason I want to use this plugin is to be able to import like this:

    import {
      my_wasm_function
    } from "../pkg";
    
    opened by ivanschuetz 2
  • Do not attempt to install wasm-pack globally via npm

    Do not attempt to install wasm-pack globally via npm

    When the script attempts to install wasm-pack if it doesn't exist, it does so with the -g flag, which by default tries to install in /usr/lib, which the running user likely has no permissions for. This is then reported as a "Rust compilation error" with no further information, leading to a wild goose chase on what the actual problem is.

    Steps to reproduce:

    1. Attempt to run any example without installing wasm-pack first, with npm available.

    Proposed fixes:

    1. Remove the -g flag.
    2. Collect stdout/stderr and give it to the user in case the command fails.
    3. Use a more descriptive error message for each subprocess call.
    opened by Selicre 1
Owner
wasm-tool
WebAssembly tooling for the web
wasm-tool
plugy empowers you to construct agnostic dynamic plugin systems using Rust and WebAssembly.

plugy plugy is a plugin system designed to enable the seamless integration of Rust-based plugins into your application. It provides a runtime environm

Geoffrey Mureithi 22 Aug 12, 2023
A Zellij plugin to fuzzy find file names and contents in style 🧐

About This Zellij plugin is a fuzzy finder for file names and their contents. It can open results in your $EDITOR (scrolled to the correct line), as f

Aram Drevekenin 11 Jun 22, 2023
Slitter is a C- and Rust-callable slab allocator implemented primarily in Rust, with some C for performance or to avoid unstable Rust features.

Slitter is a less footgunny slab allocator Slitter is a classically structured thread-caching slab allocator that's meant to help write reliable long-

Backtrace Labs 133 Dec 5, 2022
A Rust crate for automatically generating C header files from Rust source file.

Please be aware that this crate is no longer actively maintained, please look into the much more feature rich cbindgen instead. rusty-cheddar rusty-ch

Sean Marshallsay 190 Nov 12, 2022
Rust-ffi-guide - A guide for doing FFI using Rust

Using unsafe for Fun and Profit A guide to traversing the FFI boundary between Rust and other languages. A rendered version is available here. This gu

Michael Bryan 261 Dec 1, 2022
Rust library for build scripts to compile C/C++ code into a Rust library

A library to compile C/C++/assembly into a Rust library/application.

Alex Crichton 1.3k Dec 21, 2022
Rust based WASM/JS bindings for ur-rust

ur-wasm-js WASM/JS bindings for the ur-rust rust library Getting started Installation Either build the library yourself with wasm-pack or install for

Lightning Digital Entertainment 5 Feb 28, 2024
A project for generating C bindings from Rust code

cbindgen   Read the full user docs here! cbindgen creates C/C++11 headers for Rust libraries which expose a public C API. While you could do this by h

Ryan Hunt 1.7k Jan 3, 2023
Automatically generates Rust FFI bindings to C (and some C++) libraries.

bindgen bindgen automatically generates Rust FFI bindings to C (and some C++) libraries. For example, given the C header doggo.h: typedef struct Doggo

The Rust Programming Language 3.2k Jan 4, 2023
Safe interop between Rust and C++

CXX — safe FFI between Rust and C++ This library provides a safe mechanism for calling C++ code from Rust and Rust code from C++, not subject to the m

David Tolnay 4.4k Jan 7, 2023
Safe Rust bridge for creating Erlang NIF functions

Rustler Documentation | Getting Started | Example Rustler is a library for writing Erlang NIFs in safe Rust code. That means there should be no ways t

Rusterlium 3.5k Jan 7, 2023
Bridge the gap between Haskell and Rust

Curryrs Curryrs (a play on the name of Haskell Curry, rs for Rust libraries, and it's pronunciation couriers) is a library for providing easy to use b

Michael Gattozzi 296 Oct 18, 2022
Rust in Haskell FFI Example

Provides an example for using Rust in Haskell. To use this you'll need cargo, rustc, cabal and GHC installed. To execute the example run the following

Michael Gattozzi 21 Oct 1, 2022
Run Java code from Rust!

Java Native Interface Bindings for Rust This library provides complete FFI bindings to the Java Native Interface, as well as a safe and intuitive wrap

Ben Anderson 66 Nov 28, 2022
Embedding Rust in Java

Java/Rust Example An example project showing how to call into Rust code from Java. OSX Linux Windows Requirements Java 7+ Rust (tested with 1.0, night

drrb 318 Jan 1, 2023
Rust-JDBC bindings

jdbc A Rust library that allows you to use JDBC and JDBC drivers. Usage First, add the following to your Cargo.toml: [dependencies] jdbc = "0.1" Next,

Aurora 18 Feb 9, 2022
Lua 5.3 bindings for Rust

rust-lua53 Aims to be complete Rust bindings for Lua 5.3 and beyond. Currently, master is tracking Lua 5.3.3. Requires a Unix-like environment. On Win

J.C. Moyer 150 Dec 14, 2022
Safe Rust bindings to Lua 5.1

rust-lua Copyright 2014 Lily Ballard Description This is a set of Rust bindings to Lua 5.1. The goal is to provide a (relatively) safe interface to Lu

Lily Ballard 124 Jan 5, 2023
Zero-cost high-level lua 5.3 wrapper for Rust

td_rlua This library is a high-level binding for Lua 5.3. You don't have access to the Lua stack, all you can do is read/write variables (including ca

null 47 May 4, 2022