Upgrading an existing Connect app from AUI 7.x to 8.x

We are currently attempting to upgrade one of our Atlassian Connect Express apps from AUI@7.9.9 to AUI@8.x.

In our existing app, we previously loaded AUI (and jQuery) globally using <link> / <script> tags in our layout template as follows:

/views/layout.hbs

<!doctype html>
<html>
  <head>
    <link rel="stylesheet" href="{{furl '/atlassian/aui/css/aui.min.css'}}" media="all">
    <script src="{{furl '/jquery/jquery.min.js'}}"></script>
    <script src="{{furl '/atlassian/aui/js/aui.min.js'}}" type="text/javascript"></script>

From there, any JS code in our app simply assumes that there will be an AJS global.
For example our client-side code bootstraps like this:

if (AJS) {
  AJS.toInit(() => {
    try {

      // app code goes here

    } catch (e) {
      AJS.messages.error({
        title: "An error occurred",
        body: "Something went wrong"
      });
    }
  });
}

As our app is written in Typescript and bundled using Webpack, our plan has been to remove these globals and have the AJS dependencies explicitly imported by any code that references them.

With the changes to AUI 8 packaging, we figured this would be the perfect time to do this.

The plan was to remove the <link> / <script> tags from the layout template, and the above JS code becomes:

import { toInit, messages } from "@atlassian/aui";

toInit(() => {
  try {

    // app code goes here

  } catch (e) {
    messages.error({
      title: "An error occurred",
      body: "Something went wrong"
    });
  }
});

Unfortunately, it seems that the jQuery global is still needed (even though the source components appear to include their own vendored copy of jQuery), as without it, the above code results in:

Uncaught ReferenceError: jQuery is not defined.

Similarly, we were hoping that importing a component would include the styles for that component (or it would be possible to import just that component’s CSS).

In other words we were expecting that something like this would work out of the box:

import { messages } from "@atlassian/aui";

messages.success({title: "Congratulations!", body: "It works!"});

Unfortunately, the above code displays an unstyled message (no green border, no icon etc.).

It seems that we still need to include aui-prototyping.css, despite the note in the upgrade guide warning:

The ‘prototyping’ bundle of AUI is not intended to be used in production systems

As our webpack config already includes css-loader and mini-css-extract-plugin, to avoid having a <link> tag, we tried importing the prototyping CSS as follows:

import "@atlassian/aui/dist/aui/aui-prototyping.css";
import { messages } from "@atlassian/aui";

messages.success({title: "Congratulations!", body: "It works!"});

However this fails because the CSS includes SVGs for product logos, and our webpack config doesn’t have (or need) a loader for these file types.

When importing an AUI component like messages that doesn’t use any SVGs, in our opinion it should be possible to import only the styles necessary for that component.

It would be great for the documentation and/or upgrade guide to include some examples of how to import & use individual components using ES imports.

Hopefully this may improve in AUI@8.1.0 once Atlassian finish gathering requirements for the distribution.

2 Likes

Hi @scottohara, thanks for the feedback :slight_smile:

AUI 8.0’s primary focus was on improving consumption of AUI via Atlassian’s P2 plugin system. Though the team knew some developers would probably be consuming AUI via NPM, the team know of very few usages of AUI via NPM. This is one reason why the 8.0 release of AUI is awkward to consume via NPM, and why the upgrade guide lists the disclaimer.

I’ll add a link to this discussion to the ticket you referenced, so that the team that works on 8.1 will have more context to actually make it more friendly to your use-case.

Unfortunately, it seems that the jQuery global is still needed (even though the source components appear to include their own vendored copy of jQuery)

AUI still has a dependency on jQuery and, like 6.x and 7.x before it, it treats it as an external dependency. If you’re using Webpack to build your site, you will need to provide jQuery in order for AUI to work. That means you’ll either need to declare jQuery as a dependency of your package and ensure it is compiled in to your own bundle, or you’ll need to declare jQuery as an external dependency and provide it externally to webpack.

It is unclear to me what the most straightforward way of making jQuery available to AUI is. AUI can be consumed three or four discrete ways, which makes shipping it a complicated balancing act between developer ergonomics and runtime costs. As such, I don’t think it makes sense for AUI to provide a bundle of itself that includes a version of jQuery. Counter-arguments are accepted.

When importing an AUI component like messages that doesn’t use any SVGs, in our opinion it should be possible to import only the styles necessary for that component.

Disclaimer: the following advice includes usage of code that may not persist throughout the 8.x series of AUI; treat this as a prototyping experiment to test for viability.

The AUI 8.0 package ships a folder called entry, which includes definitions of entrypoints used by Webpack to create its bundles.

If you were to try one of the following things in your webpacked code:

// accesses an <aui-message> web component element constructor, 
// including CSS for the messages HTML pattern
import { MessageEl } from `@atlassian/aui/entry/aui.component.message`

// pulls in pretty much everything (including CSS, SVG references, etc), but
// is, for the moment, the only way of accessing the 'AJS.messages' variable
import { messages } from `@atlassian/aui/entry/aui.batch.components`

…then you should get access to the CSS + JS necessary for making the message component work.

Hopefully this may improve in AUI@8.1.0 once Atlassian finish gathering requirements for the distribution

I’ve started a separate discussion to push the gathering of requirements forward. AUI 8 discussion: consumption and distribution of AUI

Thanks very much for the detailed response, @daz.

We’ll give your suggestion of importing directly from @atlassian/aui/entry/* a go and see how far we get, and report our findings back here.

On the topic of jQuery, the upgrade guide mentions:

AUI considers jQuery and jQuery UI to be a deprecated implementation detail of its components and is not considered part of AUI’s canonical API.

Does this imply that eventually the AUI components will be refactored to work without jQuery, or am I reading too much into that statement?

1 Like

Unfortunately, we tried the suggestion of switching from:

import { messages } from "@atlassian/aui";

to:

import { messages } from "@atlassian/aui/entry/aui.batch.components";

…but doing so causes our Webpack build to throw the following compile error:

ModuleNotFoundError: Module not found: Error: Can't resolve 'tether' in '/node_modules/@atlassian/aui/src/js/aui/internal'

It appears that tether is a dependency installed by AUI (see package.json below), and is referenced in aui-prototyping.js.

@atlassian/aui/package.json

  "dependencies": {
    ...
    "tether": "github:atlassian/tether#amd-with-global",
    ...
  }

When attempting to import & use entrypoints directly (from @atlassian/aui/entry/*), the source components don’t seem to know how to resolve the tether dependency.

:frowning:

Hi @daz,

We are in a similar setup. Connect app, webpack and AUI 7 going to 8. The easiest way to migrate at the moment is to include the prototyping css and js (which is not recommended)

import @atlassian/aui/dist/aui/aui-prototyping';
import @atlassian/aui/dist/aui/aui-prototyping.css'; 

Would you consider aui in standalone not p2 applications in the future?

For the global jquery reference, we use the webpack provide plugin:

new webpack.ProvidePlugin({
            '$': 'jquery',
            'window.$': 'jquery',
            'window.jQuery': 'jquery',
            'jQuery': 'jquery',
            _: 'underscore'
        }

owhterwise, we include the libraries with import as needed.

Another issue is that if we want to import aui “source code” directly we would need to include your specific builders like less.

import { messages } from "@atlassian/aui/entry/aui.batch.components";