Skip to main content

Supported Browsers & Frameworks

Connect-Web supports all modern web browsers that implement the widely available fetch API and the Encoding API. The library and the generated code are compatible with ES2017 and TypeScript 4.1.

Node.js is not supported. We are working on Connect for Node.js - if you are interested, let us know on Slack or on GitHub discussions.

Connect-Web is entirely framework-agnostic and will even work with vanilla Javascript. It works out of the box with most popular application and testing frameworks including React, Remix, Svelte, Vue, Playwright and Vitest. It also integrates seamlessly with various module loaders and bundlers such as esbuild, Vite and Rollup.

However, there are some gotchas to be aware of as well as common errors that you may encounter when attempting to set up your stack. The issues vary depending on the tooling in your project. This page explains some helpful workarounds with links to examples.

Webpack

If your project is using Webpack and you are generating pure TypeScript artifacts via your buf.gen.yaml file, you are likely to see an error similar to the following:

Failed to compile.

Module not found: Error: Can't resolve '<import name>' in 'path/to/your/connect-web/genfiles'

This is because if you are using opt: target=ts as part of your plugin configuration, protoc-gen-es will generate only TypeScript files. However, these files will use imports internally that specify a .js extension. This is in accordance with the ECMAScript specification, but may cause some difficulty loading these files.

Fortunately, some workarounds exist depending on your version of Webpack.

v5.74.0 and above

If you are using Webpack v5.74.0 and above, there is an option called extensionAlias that you can add to the resolve section of your Webpack config file. This will tell Webpack how to alias TypeScript file extensions and load them properly.

For a working example, see the Webpack project in the Connect Web Integration repo.

v5.73.0 and below

If you are using a version < v5.74.0 and are not able to upgrade, then you have two options:

Output JavaScript files

Changing the target setting in your buf.gen.yaml to opt: target=js+dts will eliminate the file resolving issue as it will generate JavaScript files with a .js extension.

Note that the default generation option is target=js+dts so omitting this opt option from your config will also do the trick. For example:

- opt: target=ts
+ opt: target=js+dts

or remove altogether.

- opt: target=ts

Use the Resolve TypeScript Plugin

If you would still prefer to use opt: target=ts, it is recommended to use the Resolve TypeScript Plugin. For more details on why this is necessary, see the README of this plugin.

Note that some scaffolding tools such as Create React App and the Angular CLI both use Webpack as their underlying bundler and at press time are using a version of Webpack < 5.74.0. In addition, they discourage modification of the underlying Webpack config. Therefore, until these tools are updated to the latest version of Webpack, the recommended workaround is to use opt: target=js+dts as this is the path of least resistance.

If you've come this far and you still want to output TypeScript files, there are libraries you can use to override the Webpack config in the above tools such as react-app-rewired and Angular Builders Custom Webpack

For a working example of the above with Create React App, see the Create React App project in the Connect Web Integration repo.

Cypress

Cypress is an end-to-end testing framework that uses Webpack as its module bundler and as a result will also experience the file resolving issue. The options specified under v5.73.0 and below also apply. However, modifying the Webpack config in Cypress is a bit easier, so if you'd prefer to output TypeScript files, you'll also need a Cypress plugin called Cypress Webpack Preprocessor, which should be packaged with Cypress by default.

The Webpack overrides will need to be in your cypress.config file. An example config would look something like this:

import { defineConfig } from 'cypress'
const webpackPreprocessor = require('@cypress/webpack-preprocessor')
const ResolveTypeScriptPlugin = require('resolve-typescript-plugin')

const options = {
webpackOptions: {
resolve: {
extensions: ['.ts', '.tsx', '.js'],
plugins: [new ResolveTypeScriptPlugin()],
},
module: {
rules: [
{
test: /\.tsx?$/,
loader: 'ts-loader',
options: { transpileOnly: true },
},
],
},
},
}

export default defineConfig({
e2e: {
specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}',
baseUrl: 'http://localhost:4173',
setupNodeEvents(on, config) {
on('file:preprocessor', webpackPreprocessor(options))
},
},
})

For a working example, see the Vue project in the Connect Web Integration repo.

Parcel

Parcel is another build tool that is susceptible to the aforementioned resolver issue. With Parcel, you will see an error similar to:

@parcel/resolver-default: Cannot load file 'path/to/your/connect-web/genfiles'

As a result, the current recommendation when using Parcel is to eschew the usage of target=ts in your buf.gen.yaml file and instead to use opt: target=js+dts.

Unfortunately, if you still prefer to use target=ts, there is no workaround at this time as no plugin exists similar to the Webpack Resolve TypeScript Plugin. For more details, see this Github issue.

React Native

React Native does not offer great support for the Fetch API and the Text Encoding API. As such, React Native requires a polyfill for these two implementations. We recommend react-native-polyfill-globals to accomplish this:

  • Install the aforementioned react-native-polyfill-globals project.
  • Next, follow the Polyfill all automatically instructions under Usage.
  • Finally, apply the patches included in the project. It is recommended to use the patch-package instructions.

Unfortunately, only unary requests via the Connect protocol are supported in React Native due to some limitations in the above polyfills.

If you would like to see improved support, please give us a +1 on this issue and we will prioritize it accordingly.

For a working example, see the React Native project in the Connect Web Integration repo.

Yarn

The only issue we've found with Yarn is isolated to usage of versions 2 and above with the Plug'n'Play setup. For context, versions of Yarn from v2 onward have done away with the node_modules directory when using this configuration.

This poses a problem for generating code with Connect-Web (and its dependency protobuf-es) as these tools rely on executables in the node_modules/.bin directory. Instead, Yarn suggests using the yarn run <binary> command to execute these files. Additionally, you can run yarn bin <binary> to output the path to the binary that Yarn would run.

However, neither help because the buf.gen.yaml file requires a path to a plugin executable and does not accept a command. The suggested workaround is to use the following Bash snippet in your package.json script:

$ PATH=$(dirname $(yarn bin protoc-gen-es)):$(dirname $(yarn bin protoc-gen-connect-web)):$PATH buf generate buf.build/bufbuild/eliza

Note the above will not work on Windows, however. We recognize this is not an optimal solution, so please reach out if you'd like to see this better supported.

Finally, as mentioned above, this is only an issue with the Yarn PnP setup. Fortunately, it is possible to use Yarn 2+ without PnP. If you would like to do so, the instructions can be found in Yarn's documentation.

Note: when following these steps, notice that the step requiring nodeLinker: node-modules in your .yarnrc.yml file uses a hyphen in node-modules (not the usual underscore).

The Connect Web Integration repo provides a working example for using Yarn in Plug'n'Play mode and Yarn in unplugged mode.

Jest

There is one configuration to be aware of when using Jest in concert with the opt: target=ts option in buf.gen.yaml.

For Jest to find Connect-Web artifacts, you will need to specify a moduleNameMapper option in your package.json file as follows:

{
"name": "buf-cra",
"version": "0.1.0",
"private": true,
"dependencies": {
"@bufbuild/connect-web": "0.1.0",
"@bufbuild/protoc-gen-connect-web": "0.1.0",
"@bufbuild/protoc-gen-es": "0.0.10",
"@testing-library/jest-dom": "^5.16.4",
"@types/jest": "^27.5.2",
"@types/react": "^18.0.14",
"@types/react-dom": "^18.0.5",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"ts-jest": "^28.0.5"
},
"jest": {
"moduleNameMapper": {
"(.+)\\.js": "$1"
}
}
}

For a working example, see the Create React App project in the Connect Web Integration repo.