npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

single-spa-ember

v0.2.0

Published

Helper functions for using single-spa and ember together.

Downloads

4,315

Readme

single-spa-ember

Helper functions for using single-spa and ember together.

It is available on npm as single-spa-ember, and also available on bower as single-spa-ember in case you want to use it with ember cli and need to use bower.

Overview

When you are building an ember application that you want to work as a single-spa child application, there are five things you need to implement:

Single-spa-ember will help you implement all of those except for the activity function.

Note that the loading and activity functions are part of the single-spa root application, whereas the bootstrap, mount, and unmount functions are part of a single-spa child application

API

loadEmberApp

loadEmberApp(appName, appUrl, vendorUrl) is a function that helps you implement the loading function for your ember child application. appName and appUrl are both strings and both required, whereas vendorUrl is an optional string.

// In the single-spa root application

import {declareChildApplication} from 'single-spa';
import {loadEmberApp} from 'single-spa-ember';

const appName = 'ember-app';
const loadingFunction = () => loadEmberApp(appName, '/dist/ember-app/assets/ember-app.js', '/dist/ember-app/assets/vendor.js');
const activityFunction = location => location.hash.startsWith('ember');

declareChildApplication(appName, loadingFunction, activityFunction);

singleSpaEmber

Single-spa-ember will implement the single-spa lifecyle functions for you. To use it, you call the default export as a function with a configuration object, which returns an object that has bootstrap, mount, and unmount lifecycle functions on it. The provided configuration object has the following options:

// In the ember child application
import singleSpaEmber from 'single-spa-ember';

const emberLifecycles = singleSpaEmber({
  appName: 'ember-app', // required
  createOpts: { // See https://www.emberjs.com/api/ember/2.14.1/classes/Ember.Application
    rootElement: '#ember-app',
  },
});

export const bootstrap = emberLifecycles.bootstrap;
export const mount = emberLifecycles.mount;
export const unmount = emberLifecycles.unmount;

Usage with ember cli

For the most part, you can get applications that use ember cli to work pretty seamlessly with single-spa. Maybe the biggest thing you'll have to worry about is that ember-cli assumes that it controls the entire html page, whereas a single-spa child application does not. However, usually we can achieve equivalent behavior by just loading the vendor and app bundles into the html page dynamically, instead of baking them right into the html page. Below is a description of the known things you should do when setting up an ember-cli application with single-spa:

First, since the ember cli only supports dependencies from bower, you'll need to do:

  • bower init
  • bower install single-spa-examples --save

Add the following options to your ember-cli-build.js file:

/* eslint-env node */
'use strict';

const EmberApp = require('ember-cli/lib/broccoli/ember-app');

module.exports = function(defaults) {
  let app = new EmberApp(defaults, {
    autoRun: false, // Set autoRun to false, because we only want the ember app to render to the DOM when single-spa tells it to.
    storeConfigInMeta: false, // We're making a single-spa child application, which doesn't exclusively own the html file. So we don't want to have to have a `<meta>` tag for the ember environment to be initialized.
		fingerprint: {
			customHash: null, // This is optional, just will make it easier for you to have the same url every time you do an ember build.
		},
    // Add options here
  });
  
  // Tell ember how to use the single-spa-ember library
  app.import('bower_components/single-spa-ember/amd/single-spa-ember.js', {
		using: [
			{transformation: 'amd', as: 'single-spa-ember'},
		],
	});

  return app.toTree();
};

In your single-spa root application (which is separate from anything generated by ember cli):

// root-application.js
import * as singleSpa from 'single-spa';
import {loadEmberApp} from 'single-spa-ember';

singleSpa.declareChildApplication('ember-app', loadingFunction, activityFunction);

function activityFunction(location) {
  // Only render the ember app when the url hash starts with ember
  return location.hash.startsWith('ember');
}

// single-spa-ember helps us load the script tags and give the ember app module to single-spa.
function loadingFunction() {
  const appName = 'ember-app';
  const appUrl = '/dist/ember-app/assets/ember-app.js';
  const vendorUrl = '/dist/ember-app/assets/vendor.js'; // Optional if you have one vendor bundle used for many different ember apps
  return loadEmberApp(appName, appUrl, vendorUrl);
}

In your app.js file (that is generated by ember cli)

// app.js (the ember child application)
import Ember from 'ember';
import Resolver from './resolver';
import loadInitializers from 'ember-load-initializers';
import config from './config/environment';
import singleSpaEmber from 'single-spa-ember';

// This part is generated by the ember cli
const App = Ember.Application.extend({
  modulePrefix: config.modulePrefix,
  podModulePrefix: config.podModulePrefix,
  Resolver
});

loadInitializers(App, config.modulePrefix);

export default App;

// This is the single-spa part
const emberLifecycles = singleSpaEmber({
	App, // required
	appName: 'ember-app', // required
	createOpts: { // optional
		rootElement: '#ember-app',
	},
})

// Single-spa lifecycles.
export const bootstrap = emberLifecycles.bootstrap;
export const mount = emberLifecycles.mount;
export const unmount = emberLifecycles.unmount;