Use of Libraries Questions and Best Practices

I am currently experimenting with React/Redux with WebExtensions after seeing this article.

https://hacks.mozilla.org/2017/06/introducing-filterbubbler-a-webextension-built-using-reactredux/

Just have a few questions about the “best practices” for use of libraries (might be useful for other people thinking the same).

I know that certain libraries will be excluded from review if their hash matches with these like React and ReactDOM.

So what I have done was got those minified libraries of React/React DOM and put them in a script tag and adding

externals: {
    // "node/npm module name": "name of exported library variable"
    "react": "React",
    "react-dom": "ReactDOM"
},

to the webpack config so it doesn’t import those libraries in the bundled file.

Now that just leaves with the other libraries like redux, redux-webext, etc.

So what would be a good way to bundle the rest of the libraries for the sake of a easier review?

  • Do the same thing as React/React Dom
  • Bundle application code and library code together (1 file)
  • Separate bundles for application code and library code (2 files)

I have a genuine question: Why would you even “pack” your code?

I don’t see an advantage, but a couple of disadvantages with that:

  • You cant load scripts on demand. By design, everything has to be loaded at once, blocking the extensions startup.
  • Debugging sucks. Stack traces are incorrect and you have to step through one very long file, which makes it harder to find the places to set breakpoints.
  • Source maps are quite big and if they need to be loaded quite defensively not good for performance. So would you include them in your final build? Not doing so means you need to manually translate any stack traces of reported errors. If you include it, browsers will need to load it as soon as an error is thrown. Also, form my experience, stepping through source-mapped code can sometimes be wired.

With extensions, many of the usual advantages of packing your files don’t really matter:

  • With modern browsers, you don’t need transpilers. Chrome, Edge and Firefox support ES6, (most of?) ES7 and async functions out of the box. The only thing you can’t do is export/import.
  • The files don’t need to be loaded over the network. The time it takes to load individual files is very, very short. Also, slicing the work up into multiple files should increase the responsiveness of the browser a bit, and bottom line shouldn’t make a difference especially if multiple extensions and other things are loaded in parallel.

So if the export/import is the only reason, why don’t you only transpile that into define/require calls? It’s what transpilers do with is anyway (and that is semantically wrong, by the way).

To answer your question: I would keep everything in separate files.

So if the export/import is the only reason, why don’t you only transpile that into define/require calls? It’s what transpilers do with is anyway (and that is semantically wrong, by the way).

I would still need a transpiler to convert the React/JSX code into something browsers can read. Example from the React website.

<div className="shopping-list">
  <h1>Shopping List for {props.name}</h1>
  <ul>
    <li>Instagram</li>
    <li>WhatsApp</li>
    <li>Oculus</li>
  </ul>
</div>
React.createElement(
  "div",
  { className: "shopping-list" },
  React.createElement(
    "h1",
    null,
    "Shopping List for ",
    props.name
  ),
  React.createElement(
    "ul",
    null,
    React.createElement(
      "li",
      null,
      "Instagram"
    ),
    React.createElement(
      "li",
      null,
      "WhatsApp"
    ),
    React.createElement(
      "li",
      null,
      "Oculus"
    )
  )
);

I wonder if there’s a way to still do that but maintain separate files for the application/UI code?

Edit: I guess there’s the Webpack Aggressive-Splitting-Plugin that I could try.

To answer your question: I would keep everything in separate files.

Luckily for some of the libraries like redux/react-redux, they do provide the unminified dist file.

I wonder if there’s a way to still do that but maintain separate files for the application/UI code?

I am sure you can configure babel to transpile all your files separately into an output folder. Probably even with a watch command.

And then there is one more option: You could just not use JSX. If you write it like this, it doesn’t look very different and is pure JavaScript:

_('div', { className: "shopping-list", },
  _('h1', 'Shopping List for {props.name}'),
  _('ul',
    _('li', 'Instagram'),
    _('li', 'WhatsApp'),
    _('li', 'Oculus'),
  ),
);

function _(tag, props, ...children) {
    if (
        props && typeof props === 'object' && props.constructor
        && props.constructor.name === 'Object')
    { // (most likely) object literal
        return React.createElement(tag, props, ...children);
    } else {
        return React.createElement(tag, null, props, ...children);
    }
}

But that is obviously up to you.

1 Like

So I uploaded History AutoDelete redone in React/Redux and got these warnings:

https://addons.mozilla.org/en-US/developers/upload/40962fbdc5d147ca9d00cd642efc31c6

My extension got auto approved for update so it’s not really a concern now (Edit: just had to upload a patch, which means that version is in review now), but as a future reference, are these warnings fine if they are from established libraries(Redux/React-Redux)?

Also, another weird thing is the validator did not pick up react-dom.min.js, which has the same hash as this line:

The automated linting is mostly really just to give you and the reviewer hints about what might be wrong.

It’s also pretty easy to fool those tests, if you want to …

The manual review is what matters.