JavaScript private class methods with Snowpack
Asked Answered
R

2

7

I use private JavaScript class methods in my front-end code and Snowpack for my development workflow.

Currently (as of v2.15.0-pre.5), Snowpack doesn't seem to play well with private class methods, i.e., the following fails to when building with snowpack build:

export class TestClass {
  #test() {
    console.log("testing...");
  }

  test() {
    this.#test();
  }
}

A repo to reproduce is here. After cloning, run:

npm install
npm run build

I've opened an issue with Snowpack, but apparently the problem lays in the integration with Rollup and the fix isn't a priority.

As far as I understand, to solve it we need:

I wonder if anyone could help with an example of this, before I dive deep into learning Rollup ecosystem?

Or maybe there's another way to make it work?

I'm now back to using _methodName instead of #methodName due to time constraints, but I plan to contribute a fix when time allows.

Restraint answered 20/10, 2020 at 2:34 Comment(6)
Using a custom Rollup plugin for Snowpack to inject acorn-private-methods into acornInjectPlugins does not appear to work correctly, from my testing. It seems this only applies to the project sources, and not dependencies; this appears consistent with what FredKSchott mentions on the linked GitHub issue: "because mod101 is treated as a dependency, it goes through a different workflow". I think a different approach might be necessary.Unmoving
@concision, interesting! Thanks for taking time to verify this. Snowpack already works well with private methods in the project sources, as is, with acorn-private-methods injection.Restraint
@concision, I've figured it out. Your comment was helpful too, it gave me an idea to look at other Rollup hooks. Maybe you could tweak you gist and post it as an alternative answer, I'd be happy to reward it with the bounty. Thanks!Restraint
Glad to hear it was of some help. I am surprised that no one seems to have ran into this issue before. This might be useful for future readers, so I am thinking I will package the solution as both a rollup and snowpack plugin available on npm and post those as an answer. Might take a day or two.Unmoving
@concision, that'd be great, thanks! I've made this snowpack plugin already as I prefer declarative JSON config to snowpack.config.js . It'd be great if you could make it configurable via the pluginOptions arg, like specifying what exact Acorn plugins to use.Restraint
I have added an answer with a plugin implementation as you have described. It is available on NPM as snowpack-plugin-acorn-injection. This supports declarative JSON Snowpack configurations.Unmoving
U
5

Snowpack Plugin: snowpack-plugin-acorn-injection

Expanding off of @noseratio's work, I have created a NPM dependency called snowpack-plugin-acorn-injection that will inject the relevant Acorn plugins into Rollup's internal configuration.

The plugin is available:


Example

Dependency Installation

Install the plugin and the relevant Acorn plugin(s) that are desired (for example, acorn-stage3) as development dependencies.

Steps:

  • npm:
    npm install --save-dev snowpack-plugin-acorn-injection acorn-stage3
    
  • Yarn:
    yarn add --dev snowpack-plugin-acorn-injection acorn-stage3
    

Configure Snowpack

Configure the project's Snowpack configuration with snowpack-plugin-acorn-injection and the relevant Acorn plugins:

{
  ...
  "plugins": [
    [
      "snowpack-plugin-acorn-injection",
      {
        "plugins": [
          "acorn-stage3"
        ]
      }
    ]
  ],
  ...
}
Unmoving answered 24/10, 2020 at 21:1 Comment(0)
R
3

I've figured it out, using Rollup.js options hook and acorn-stage3 acorn plugin, repo.

acorn-private-methods can be used as well (if only private methods wanted).

  • Create a custom Rollup.js plugin, I called it @noseratio/rollup-acorn-conf:
"use strict";

module.exports = function plugin(hostOpts = {}) {
  return { 
    name: 'rollup-acorn-conf',

    options: rollupOpts => { 
      console.log("Enabling 'acorn-stage3'...");
      rollupOpts.acorn = rollupOpts.acorn ?? {};
      rollupOpts.acorn.ecmaVersion = 2020;
      rollupOpts.acornInjectPlugins = rollupOpts.acornInjectPlugins ?? [];
      rollupOpts.acornInjectPlugins.push(require('acorn-stage3'));
      return rollupOpts;
    }
  };
};

Its package.json:

{
  "name": "@noseratio/rollup-acorn-conf",
  "version": "0.1.1",
  "description": "Enable ES2020 features (Stage 3) for Rollup.js",
  "homepage": "https://github.com/noseratio/snowpack-discussions-1209",
  "main": "index.js",
  "scripts": {},
  "devDependencies": {
    "acorn-stage3": "^4.0.0"
  }
}
  • In snowpack.config.js:
  installOptions: {
    rollup: { 
      plugins: [require('@noseratio/rollup-acorn-conf')()]
    }
  }
Restraint answered 23/10, 2020 at 14:15 Comment(1)
A gist for declarative snowpack.config.json.Restraint

© 2022 - 2024 — McMap. All rights reserved.