Version: 5.x

single-spa-alpinejs

single-spa-alpinejs is a helper library for mounting alpinejs components as single-spa applications or parcels.

  1. npm install --save single-spa-alpinejs
  2. # or
  3. yarn add single-spa-alpinejs

Alternatively, you can use single-spa-alpinejs from a CDN as a global variable:

  1. <script src="https://cdn.jsdelivr.net/npm/single-spa-alpinejs"></script>

Note that you might want to lock down the package to a specific version. See here for how to do that.

  • There are three ways the you can define AlpineJS components as single-spa applications or parcels.

  • The simplest way where the template contains all the required data and initialization logic (including x-data and x-init) as part of the dom. The template is provided via the options attribute template

  • You could also provide x-data externally and the helper will add it to the component.

    • The x-data can be provided in the following forms (via the options attribute xData)
      • an object
      • a function that returns an object
      • a function that returns a promise which resolves with an object.
  • You can also provide x-init externally along with the x-data and the helper will add it to the component.

  • The x-init can be provided in the following forms (via the options attribute xInit) and needs to be a function.

  • Please note the xData attribute must be provided otherwise the xInit attribute will be ignored.

  • The sample below references the example from the Alpine Toolbox - Alpine JS and fetch() and demonstrates how you can use the xInit and xData attributes to create an AlpineJS application .

  1. import singleSpaAlpinejs from 'single-spa-alpinejs';
  2. const alpinejslifecycles = singleSpaAlpinejs({
  3. template: `
  4. <div class="rounded overflow-hidden shadow-lg font-sans p-1 m-1"
  5. x-data="{ open: false }">
  6. <div class="font-bold p-1">Example for x-show attribute</div>
  7. <button class="bg-transparent hover:bg-blue-500 text-blue-700 font-semibold
  8. hover:text-white py-2 px-4 border border-blue-500
  9. hover:border-transparent rounded"
  10. @click="open = !open">Open/Close</button>
  11. <div x-show="open" class="text-4xl">
  12. Hey, I'm open
  13. </div>
  14. </div>`,
  15. });
  16. export const bootstrap = alpinejslifecycles.bootstrap;
  17. export const mount = alpinejslifecycles.mount;
  18. export const unmount = alpinejslifecycles.unmount;

Example usage when installed via CDN:

  • The usage is similar and once the library is loaded it will be available globally and accessed via the window object.
  1. const alpinejsApp = window.singleSpaAlpinejs({
  2. template: `
  3. <div class="rounded overflow-hidden shadow-lg font-sans p-1 m-1"
  4. x-data="{ open: false }">
  5. <div class="font-bold p-1">Example for x-show attribute</div>
  6. <button class="bg-transparent hover:bg-blue-500 text-blue-700 font-semibold
  7. hover:text-white py-2 px-4 border border-blue-500
  8. hover:border-transparent rounded" @click="open = !open">Open/Close</button>
  9. <div x-show="open" class="text-4xl">
  10. Hey, I'm open
  11. </div>
  12. </div>`,
  13. });
  14. singleSpa.registerApplication({
  15. name: 'name',
  16. app: alpinejsApp,
  17. activeWhen: () => true,
  18. });
  1. import singleSpaAlpinejs from 'single-spa-alpinejs';
  2. const alpinejslifecycles = singleSpaAlpinejs({
  3. template: `
  4. <div class="rounded overflow-hidden shadow-lg font-sans p-1 m-1">
  5. <div class="font-bold p-1">Example for x-show attribute</div>
  6. <button class="bg-transparent hover:bg-blue-500 text-blue-700 font-semibold
  7. hover:text-white py-2 px-4 border border-blue-500
  8. hover:border-transparent rounded" @click="open = !open">Open/Close</button>
  9. <div x-show="open" class="text-4xl">
  10. Hey, I'm open
  11. </div>
  12. </div>`,
  13. xData: { open: false },
  14. });
  15. export const bootstrap = alpinejslifecycles.bootstrap;
  16. export const mount = alpinejslifecycles.mount;
  17. export const unmount = alpinejslifecycles.unmount;
  1. import singleSpaAlpinejs from 'single-spa-alpinejs';
  2. const appTemplate = `
  3. <div class="w-full h-full text-gray-800">
  4. <h1 class="mt-0 mb-3 font-light text-3xl" x-text="title"><!-- title text --></h1>
  5. <p class="text-xl text-gray-600 font-light mb-4" x-html="intro"><!-- intro text --></p>
  6. <div class="flex flex-wrap -mx-2 pb-8">
  7. <!-- begin: user card -->
  8. <template x-for="user in users" :key="user.id">
  9. <div class="w-full md:w-1/2 lg:w-1/3 xl:w-1/4 h-auto font-light">
  10. <div class="flex bg-white rounded-lg shadow-md m-2 border-l-4
  11. border-white hover:shadow-2xl hover:border-pink-500
  12. cursor-pointer relative">
  13. <div class="p-4 pr-6 leading-normal">
  14. <div class="font-medium text-xl truncate" x-text="user.name"></div>
  15. <div class="truncate uppercase text-xs text-gray-500 font-semibold
  16. pb-2 tracking-widest" x-text="user.company.name"></div>
  17. <div class="" x-text="user.phone"></div>
  18. <a class="text-blue-600 hover:text-blue-700 mr-4 block"
  19. x-bind:href="'mailto:' + user.email" x-text="user.email"></a>
  20. <a class="text-blue-600 hover:text-blue-700 block"
  21. x-bind:href="'https://' + user.website" x-text="user.website"></a>
  22. </div>
  23. </div>
  24. </div>
  25. </template>
  26. <!-- end: user card -->
  27. </div>
  28. </div>
  29. `;
  30. const appDataFn = ({ title, name }) => ({
  31. title,
  32. intro:
  33. 'Implement a simple <code class="text-md text-pink-600">fetch()</code> request to render a list of items using Alpine.js :)',
  34. users: [],
  35. open: false,
  36. name,
  37. });
  38. const appXInitFn = (id) => {
  39. return fetch('https://jsonplaceholder.typicode.com/users')
  40. .then((response) => response.json())
  41. .then((data) => (document.querySelector(`#${id}`).__x.$data.users = data));
  42. };
  43. const opts = {
  44. template: appTemplate,
  45. xData: (data) => appDataFn(data), // pass props to x-data
  46. xInit: appXInitFn,
  47. };
  48. const alpinejslifecycles = singleSpaAlpinejs(opts);
  49. export const bootstrap = alpinejslifecycles.bootstrap;
  50. export const mount = alpinejslifecycles.mount;
  51. export const unmount = alpinejslifecycles.unmount;

single-spa-html is called with an object that has the following properties:

  • template (required): An HTML string or a function that returns a string. The function will be called with the single-spa custom props. The returned string is injected into the DOM during the single-spa mount lifecycle.
  • domElementGetter (optional): A function that returns the dom element container into which the HTML will be injected. If omitted, a default implementation is provided that wraps the template in a <div> that is appended to document.body.
  • xData (optional): An object or a function or a function that returns a promise.The returned string is injected into the DOM as the x-data attribute during the single-spa mount lifecycle.
  • xInit (optional): A function or a function that returns a promise. The function provided is added to the global scope and the function initiation along with the root dom element id as a parameter is injected into the DOM as the x-init attribute during the single-spa mount lifecycle. Please note the xData attribute must be provided otherwise the xInit attribute will be ignored. The function you provide xInit

  • This section covers the details of how xData and xInit option attributes are processed by the single spa helper.

  • Consider the example below

  1. const appDataFn = () => { open: false, loading: true }
  2. const appXInitFn = (domId) => {
  3. console.log('Hello from appXInitFn');
  4. // domId provides access to the parent dom element where x-data and x-init are defined
  5. document.querySelector(`#${domId}`).__x.$data.loading = false
  6. }
  7. const opts = {
  8. template: appTemplate, // base template
  9. xData: (data) => appDataFn(data), // pass props to x-data
  10. xInit: appXInitFn, // x-Init function
  11. };
  12. const alpinejsApp = singleSpaAlpinejs(opts);
  13. singleSpa.registerApplication({
  14. name: 'myapp',
  15. app: alpinejsApp,
  16. activeWhen: () => true,
  17. });
  • The helper does the following

    • Adds the template to the dom wrapped in parent dom element with and id that has a prefix of alpine. In this case it will be id='alpine-myapp'
    • Attaches a resolved xData as a string x-data="{ "name": "myapp" ,"open": false }" to the parent dom element.
    • It will make the user defined appXInitFn available globally as an attribute of window.singleSpaAlpineXInit and will be accessible via variable window.singleSpaAlpineXInit.myapp
    • Attaches a resolved xInit as a string that calls the globally defined variable x-init="singleSpaAlpineXInit.myapp('alpine-myapp')" to the parent dom element.
    • Note that this also passes id of the parent dom element which can then be used to access the alpine data elements to update the state as required.

    • You may have special characters in the application name for example @my/app. See the example below

    1. singleSpa.registerApplication({
    2. name: '@my/app',
    3. app: alpinejsApp,
    4. activeWhen: () => true,
    5. });
    • The single spa helper converts these to valid global function names by replacing all the special characters with underscores (_). This does not require any special handling from the user as the helper takes care of this internally

    • In the above case the xInit dom element would look like the following x-init="singleSpaAlpineXInit._my_app('alpine-@my/app')" where the xInit function is available as a global variable _my_app.

AlpineJS - 图1Edit this page