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

@marko/rollup

v4.0.3

Published

A Marko plugin for Rollup

Downloads

28

Readme

A Marko plugin for Rollup.

Features

  1. Compiles Marko templates for the server and browser.
  2. Externalizes styles to be consumed by other tools (eg: rollup-plugin-postcss).
  3. Can calculate browser dependencies for a page template and send only templates with components to the browser.
  4. Can output a bundle which automatically initializes Marko components.
  5. Can create a linked build for both the server and browser with automated asset management.

Note: The Marko runtime is authored in commonjs, this means the @rollup/plugin-commonjs is required!

Installation

npm install @marko/rollup

Basic example config

import nodeResolve from "@rollup/plugin-node-resolve";
import commonjs from "@rollup/plugin-commonjs";
import marko from "@marko/rollup";

export default {
  ...,
  plugins: [
    marko.browser(),
    nodeResolve({
      browser: true,
      extensions: [".js", ".marko"]
    }),
    // NOTE: The Marko runtime uses commonjs so this plugin is also required.
    commonjs({
      extensions: [".js", ".marko"]
    }),
    // If using `style` blocks with Marko you must use an appropriate plugin.
    postcss({
      external: true
    })
  ]
};

Likewise, if bundling the components for the server use marko.server() as the plugin.

Linked config

If you use both the server and browser plugins (in a multi rollup config setup) @marko/rollup will go into a linked mode. In the linked mode you will have access to the <rollup> tag on the server, and the browser config will automatically have the input option set.

export default [{
  // Config object for bundling server assets.
  input: "src/your-server-entry.js",
  plugins: [
    marko.server()
    ...
  ]
}, {
  // Config object for bundling browser assets.
  plugins: [
    marko.browser()
    ...
  ]
}];

<rollup> tag

In a linked setup you have access to the <rollup> tag which will provide two tag parameters that allow you to write out the asset links for your server rendered app.

The first parameter entry is the generated input name that the server plugin gave to the browser compiler. You can use it to find the corresponding entry chunk from rollups build.

The second parameter output is an array of AssetInfo | ChunkInfo objects with most of the same properties returned from rollup's generateBundle hook. Some properties have been stripped, notably code and map since they would be too large to inline directly. A size property is also available for all chunks to allow you to be able to filter out empty chunks, or inline chunks of certain size.

<head>
  <rollup|entry, output|>
    $ const entryChunk = output.find(chunk => chunk.name === entry);

    <if(entryChunk.size /* skip scripts all together if empty js file */)>
      <for|fileName| of=entryChunk.imports>
        <link rel="modulepreload" href=fileName/>
      </for>

      <script async type="module" src=entryChunk.fileName/>
    </if>
  </rollup>
</head>

Ultimately it is up to you to map the chunk data (sometimes referred to as a manifest) into the <link>'s and <script>'s rendered by your application.

If your rollup browser config contains multiple output options, or you have multiple browser configs, all of the chunks for each output are passed into the <rollup> tag.

For example if you have an esm and iife build:

{
  plugins: [
    marko.browser()
    ...
  ],
  output: [
    { dir: 'dist/iife', format: 'iife' },
    { dir: 'dist/esm', format: 'esm' }
  ]
}

we could access the assets from both builds:

<head>
  <rollup|entry, iifeOutput, esmOutput|>
    $ const iifeEntryChunk = iifeOutput.find(chunk => chunk.name === entry);
    $ const esmEntryChunk = esmOutput.find(chunk => chunk.name === entry);

    <script async type="module" src=esmEntryChunk.fileName/>
    <script nomodule src=iifeEntryChunk.fileName></script>
  </rollup>
</head>

and boom you now have a module/nomodule setup.

Top level components

Marko was designed to send as little JavaScript to the browser as possible. One of the ways we do this is by automatically determining which templates in your app should be shipped to the browser. When rendering a template on the server, it is only necessary to bundle the styles and interactive components rendered by that template.

To send the minimal amount of Marko templates to the browser you can provide a Marko template directly as the input. This will also automatically invoke code to initialize the components in the browser, so there is no need to call template.render yourself in the browser.

Note: if you are using linked plugins then the server plugin will automatically tell the browser compiler which Marko templates to load.

export default {
  input: "./my-marko-page.marko",
  plugins: [
    marko.browser(),
    ...
  ],
  ...
}

Options

Both the server and browser plugins can receive the same options.

options.babelConfig

You can manually override the Babel configuration used by passing a babelConfig object to the @marko/rollup plugin. By default Babels regular config file resolution will be used.

marko.browser({
  babelConfig: {
    presets: ["@babel/preset-env"],
  },
});

options.runtimeId

In some cases you may want to embed multiple isolated copies of Marko on the page. Since Marko relies on some window properties to initialize this can cause issues. For example, by default Marko will read the server rendered hydration code from window.$components. In Marko you can change these window properties by rendering with { $global: { runtimeId: "MY_MARKO_RUNTIME_ID" } } as input on the server side.

This plugin exposes a runtimeId option produces output that automatically sets $global.runtimeId on the server side and initializes properly in the browser.

const runtimeId = "MY_MARKO_RUNTIME_ID";
// Make sure the `runtimeId` is the same across all of your plugins!
marko.server({ runtimeId });
marko.browser({ runtimeId });

options.serialize

This option is only available for the browser plugin. It allows you to transform the list of chunks serialzed in a linked config to include whatever you like. For example if you did want to include the code property from the rollup chunk, to say inline some content, the following would work:

marko.browser({
  serialize(output) {
    return output.map((chunk) =>
      chunk.type === "asset"
        ? {
            type: "asset",
            fileName: chunk.fileName,
          }
        : {
            type: "chunk",
            name: chunk.name,
            isEntry: chunk.isEntry,
            fileName: chunk.fileName,
            code:
              chunk.code.replace(/^\s+$/, "").length < 1024
                ? chunk.code
                : undefined, // only inline small code chunks
          }
    );
  },
});

Code of Conduct

This project adheres to the eBay Code of Conduct. By participating in this project you agree to abide by its terms.