KanoComputing / kano-code

👩‍💻👨‍💻Kano Code
https://world.kano.me
GNU General Public License v2.0
16 stars 5 forks source link

Consume library using webpack instead of es6-server to use typescript #1815

Open FWeinb opened 4 years ago

FWeinb commented 4 years ago

The first (fixable) issue is that we have to expose the Tone module as window.Tone because Tone is distributed as an UMD module and webpack is using the ES6 export (this can be done using webpack.ProvidePlugin see below).

Another issue I am currently facing is that the dynamic fetching of l18n information here makes it impossible(?) for webpack to extract these files and bundles them into the final applications. My current workaround is to just copy the localisation into the destination manually.

This issue also applies to all other media fiels as all these aren't loaded in a way webpack can recognise them. (See default-resources.ts)

Any idea how this could be solved?

It looks like you are using rollup on http://world.kano.me so there should be a nice way to bundle this library into an application.

This also prevents kano-code (among another #1816) to be used on codesandbox.io which would be a great place to host the examples you are providing.

.babelrc
{
  "presets": [
    ["@babel/preset-env", { "targets": { "browsers": ["chrome 70"] } }],
    ["@babel/preset-typescript"]
  ],
  "plugins": [
    [
      "@babel/plugin-proposal-decorators",
      {
        "legacy": true
      }
    ],
    "@babel/proposal-class-properties",
    "@babel/proposal-object-rest-spread"
  ]
}
webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');

module.exports = {
  entry: path.resolve(__dirname, 'src', 'index'),

  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  },

  resolve: {
    extensions: ['.ts', '.tsx', '.js', '.json']
  },

  module: {
    rules: [
      { test: /\.(ts|js)x?$/, loader: 'babel-loader', exclude: /node_modules/ }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    }),
    new webpack.ProvidePlugin({
      'window.Tone': 'tone',
      'window.marked': 'marked',
      'window.js_beautify': 'js-beautify'
    })
  ]
};
pazdera commented 4 years ago

Hey @FWeinb, thanks for taking a look at this. This repo is intended to be used as a library - we use it internally across a number of products using rollup as you say.

We’ve done some experiments with webpack recently, so someone might be able to give you some pointers on this or see what we could do about this.

Personally, I’d be happy to accept fixes to make it work with webpack or on codesandbox.io if we can maintain the current feature set.

Thanks!

joe-thom commented 4 years ago

Hey @FWeinb, thanks for raising this for us. As @pazdera mentioned above we are currently doing some experiments using webpack ourselves! Our current workaround for importing locale files (and others) is to use CopyWebpackPlugin to copy the files directly from the kano-code node_modules directory and provide them to the front-end via an alias url. You should then be able to load them by passing the alias urls into the i18n.load() params. I've put an example below:

.webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const webpack = require('webpack');

module.exports = {
  entry: path.resolve(__dirname, 'src', 'index'),

  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  },

  resolve: {
    extensions: ['.ts', '.tsx', '.js', '.json']
  },

  module: {
    rules: [
      { test: /\.(ts|js)x?$/, loader: 'babel-loader', exclude: /node_modules/ }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    }),
    new webpack.ProvidePlugin({
      'window.Tone': 'tone',
      'window.marked': 'marked',
      'window.js_beautify': 'js-beautify'
    }),
    new CopyWebpackPlugin([
      {
        context: 'node_modules/@webcomponents',
        from: '**/*.js',
        to: 'webcomponents',
      },
      {
        from: 'node_modules/@kano/code/locale',
        to: 'kanocode/locale',
      },
      {
        from: 'node_modules/@kano/kwc-blockly',
        to: 'kanomodules/@kano/kwc-blockly',
      },
    ]),
  ]
};

index.js

import * as code from '@kano/code/index.js';
import * as i18n from '@kano/code/i18n.js';

const lang = i18n.getLang();
i18n.load(lang,
  { 
    blockly: true,
    modulesPath: `${window.location.origin}/kanomodules`,
    kanoCodePath: `${window.location.origin}/kanocode`
  }).then(() => {
    this.editor = new code.Editor();
    this.editor.inject(document.body);
});

It's a bit clunky at the moment and we will most likely improve the way to do this in the future but hope this helps for now 👍

FWeinb commented 4 years ago

Thanks for your help @joe-thom! Your solution is working beautifully. This library is really well build and documented! Thanks for making this open-source.

After getting this running I made an initial effort in building some blocks to interact with LEGO® Powered Up using WebBluetooth.

I made a little video showing it in action (click on image) Thumbnail of video showing custom Powered Up Hub in action

Clicking on the button in the output will change the LED on the hub to a random color. Pressing the button on the Hub will in turn change the background color in the output. In the future I will add some more blocks to control connected motors and other sensors.

Adding this to kano-code was really easy, thanks again for building this!

joe-thom commented 4 years ago

@FWeinb glad that solved your problem and thanks for sending over the video - here at Kano we love seeing people use our tools in interesting ways (have shared with the rest of the team)!

I'll leave the issue open for the moment as it would be great to get a permanent solution for this implemented in the future which could maybe also solve getting it working in environments like codesandbox.io.

Thanks again for raising this!