surma/rollup-plugin-off-main-thread

Request: Redux-React-Comlink Example for ie11 Target

sdykae opened this issue · 2 comments

Hi, Is there a way to bundle build rollup-plugin-off-main-thread + comlink + redux, transpiling to es5 from rollup?
I've been trying to achive this but when AMD is set in rollup, ES6/7 code is apended to Module resolution and I dont know how to handle an AMD bundle to ES5 with rollup ;c

/**
 * Copyright 2018 Google Inc. All Rights Reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *     http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// If the loader is already loaded, just stop.
if (!self.define) {
  const singleRequire = async name => {
    if (name !== 'require') {
      name = name + '.js';
    }
    if (!registry[name]) {
      
        await new Promise(async resolve => {
          if ("document" in self) {
            const script = document.createElement("script");
            script.src = name;
            document.head.appendChild(script);
            script.onload = resolve;
          } else {
            importScripts(name);
            resolve();
          }
        });
      

      if (!registry[name]) {
        throw new Error(`Module ${name} didn’t register its module`);
      }
    }
    return registry[name];
  };

  const require = async (names, resolve) => {
    const modules = await Promise.all(names.map(singleRequire));
    resolve(modules.length === 1 ? modules[0] : modules);
  };
  
  // FIXME: This is probably not generic, lol.
  require.toUrl = id => `./${id}`;

  const registry = {
    require: Promise.resolve(require)
  };

  self.define = (moduleName, depsNames, factory) => {
    if (registry[moduleName]) {
      // Module is already loading or loaded.
      return;
    }
    registry[moduleName] = new Promise(async resolve => {
      let exports = {};
      const module = {
        uri: location.origin + moduleName.slice(1)
      };
      const deps = await Promise.all(
        depsNames.map(depName => {
          if (depName === "exports") {
            return exports;
          }
          if (depName === "module") {
            return module;
          }
          return singleRequire(depName);
        })
      );
      const facValue = factory(...deps);
      if(!exports.default) {
        exports.default = facValue;
      }
      resolve(exports);
    });
  };
}

I've been testing with worker-plugin but I stuck in
image
to do this I had to polyfill the main thread and the worker, dont know why ;'v (symbol and other errors in the worker)
webpack.config.js

const CopyWebpackPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const WorkboxWebpackPlugin = require('workbox-webpack-plugin');
const path = require('path');
const webpack = require('webpack');
const WorkerPlugin = require('worker-plugin');

const extensions = ['.js', '.jsx', '.ts', '.tsx'];
const babelRc = {
  presets: [
    [
      '@babel/preset-env',
      {
        modules: false,
        targets: {
          ie: 11
        },
        useBuiltIns: 'entry',
        corejs: 3
        // debug: true
      }
    ],
    '@babel/preset-typescript'
  ],
  plugins: [
    ['@babel/plugin-syntax-dynamic-import'],
    [
      '@babel/plugin-proposal-decorators',
      { decoratorsBeforeExport: true }
    ],
    ['@babel/plugin-proposal-class-properties', { loose: true }]
    // ['@babel/plugin-transform-arrow-functions']
  ]
};

module.exports = {
  devtool: 'source-map',
  devServer: {
    historyApiFallback: true
  },
  mode: 'development',
  module: {
    rules: [
      {
        test: /\.(ts|js|mjs)x?$/,
        exclude: [
          /@babel(?:\/|\\{1,2})runtime|core-js/,
          /canvas-datagrid/
        ],
        use: [
          {
            loader: 'thread-loader',
            options: {}
          },
          {
            loader: 'cache-loader'
          },
          {
            loader: 'babel-loader',
            options: babelRc
          }
        ]
      },
      {
        test: /\.html$/,
        loader: 'html-loader'
      }
      // {
      //   test: /\.worker\.ts$/,
      //   use: { loader: 'worker-loader' }
      // }
    ]
  },
  resolve: {
    extensions: ['.js', '.ts', '.mjs']
  },
  plugins: [
    new CopyWebpackPlugin([
      // 'images/**',
      // 'node_modules/@webcomponents/webcomponentsjs/**',
      // 'manifest.json'
      'index.html'
    ]),
    // new HtmlWebpackPlugin({
    //   chunksSortMode: 'none',
    //   template: 'index.html'
    // }),
    // new WorkboxWebpackPlugin.GenerateSW({
    //   include: ['index.html', 'manifest.json', /\.js$/],
    //   exclude: [/\/@webcomponents\/webcomponentsjs\//],
    //   navigateFallback: 'index.html',
    //   swDest: 'service-worker.js',
    //   clientsClaim: true,
    //   skipWaiting: true,
    //   runtimeCaching: [
    //     {
    //       urlPattern: /\/@webcomponents\/webcomponentsjs\//,
    //       handler: 'staleWhileRevalidate'
    //     },
    //     {
    //       urlPattern: /^https:\/\/fonts.gstatic.com\//,
    //       handler: 'staleWhileRevalidate'
    //     }
    //   ]
    // })
    new WorkerPlugin(
      {
        // disable warnings about "window" breaking HMR:
        globalObject: false
      }
    )

  ]
};

index.js


import 'core-js/stable';
import 'regenerator-runtime/runtime';

// import '@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js';
// import '@webcomponents/webcomponentsjs/webcomponents-bundle.js';

import 'proxy-polyfill';
import React from "react";
import ReactDOM from "react-dom";

import { Provider, connect } from "react-redux";

import { html } from "htm/react/index";

import { wrap } from "comlink";

import remoteStoreWrapper from "./remote-store-wrapper";

async function run() {
  const remoteStore = await wrap(new Worker("./worker.ts", { type: 'module' }));
  const store = await remoteStoreWrapper(remoteStore);

  const CounterDemo = connect(counter => ({ counter }))(
    ({ counter, dispatch }) => html`
      <div>
        <h1>Welcome</h1>
        <p>The current counter is: ${counter}</p>
        <button onClick=${() => dispatch({ type: "INCREMENT" })}>+</button>
        <button onClick=${() => dispatch({ type: "DECREMENT" })}>-</button>
      </div>
    `
  );

  ReactDOM.render(
    html`
      <${Provider} store=${store}> <${CounterDemo} /> <//>
    `,
    document.getElementById("root")
  );
}
run();

worker.js

import 'core-js/stable';
import 'regenerator-runtime/runtime';

import 'proxy-polyfill';
// import 'core-js/es/symbol';
// import 'core-js/es/weak-set'
import { createStore } from "redux";

import { expose } from "comlink";

const reducer = (state = 0, { type }) => {
  switch (type) {
    case "INCREMENT":
      return state + 1;
    case "DECREMENT":
      return state - 1;
    default:
      return state;
  }
};

const store = createStore(reducer);
expose(store);

I dont know how to do this with webpack or rollup, maybe parcel? ;'c

I've got some progress on my https://github.com/sdyalor/comlink.pwa with Proxy polyfill

surma commented

This is now effectively a duplicate of #19