Shopify / quilt

A loosely related set of packages for JavaScript/TypeScript projects at Shopify
MIT License
1.68k stars 219 forks source link

web-worker doesn't work with typescript and nextjs #2753

Open iSuslov opened 3 months ago

iSuslov commented 3 months ago

Overview

web-worker doesn't work with typescript and nextjs. Suggested babel-loader only works with js files. Nextjs uses webpack5 and bunch of own loaders. Adding

module: {
    rules: [
      {
        test: /\.js/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              babelrc: false,
              plugins: [require.resolve('@shopify/web-worker/babel')],
            },
          },
        ],
      },
    ],
  },

is not enough.

I was able to make it work by modifying webpack config in next.config like this:

import {WebWorkerPlugin} from '@shopify/web-worker/webpack';
/** @type {import('next').NextConfig} */
const nextConfig = {
    webpack: (config, { isServer, nextRuntime, dev }) => {
        config.module.rules.map((r) => {
            if (
                r.issuerLayer === "app-pages-browser" &&
                Array.isArray(r.use) &&
                Array.isArray(r.resolve.mainFields)
            ) {
                r.use.push({
                    loader: "babel-loader",
                    options: {
                        babelrc: false,
                        plugins: [import.meta.resolve("@shopify/web-worker/babel")],
                    },
                });
            }
            return r;
        });
        config.plugins.push(
            new WebWorkerPlugin({
                globalObject: "self",
            }),
        );

        return config;
    },
};
export default nextConfig;

So the appropriate rule looks like this:

Screenshot 2024-04-09 at 3 40 45 AM

But this solution feels flakey.

Consuming repo

https://github.com/Shopify/quilt/tree/main/packages/web-worker

Scope


Checklist

iSuslov commented 3 months ago

This configuration allows dev server to run:

import { WebWorkerPlugin } from "@shopify/web-worker/webpack";

/** @type {import('next').NextConfig} */
const nextConfig = {
    webpack: (config, { isServer, nextRuntime, dev }) => {
        if (!isServer) {
            config.plugins.push(
                new WebWorkerPlugin({
                    globalObject: "self",
                }),
            );
            config.module.rules.push({
                test: /\.(ts|tsx)/,
                exclude: /node_modules/,
                use: [{
                    loader: 'babel-loader',
                    options: {
                        babelrc: false,
                        plugins: ['@shopify/web-worker/babel'],
                        presets: ["@babel/preset-typescript"]
                    }
                }]
            })
        }
    }
}
export default nextConfig

But build still fails:

TypeError: finalInputFileSystem._writeVirtualFile is not a function at VirtualModulesPlugin.writeModule (/Users/user/Projects/p/node_modules/webpack-virtual-modules/lib/index.js:155:30) at Object.pitch (/Users/user/Projects/p/node_modules/@shopify/web-worker/build/cjs/webpack-parts/loader.js:88:29)