Hone logo
Hone
Problems

Vue Component Bundling with a Custom Rollup Plugin

This challenge focuses on creating a custom Rollup plugin to bundle Vue components within a Vue project. Many projects benefit from custom bundling strategies, such as optimizing component sizes, pre-compiling templates, or injecting specific metadata. This exercise will guide you through building a simple plugin that transforms Vue component files (.vue) into JavaScript modules.

Problem Description

You are tasked with creating a Rollup plugin that processes .vue files and transforms them into standard JavaScript modules suitable for bundling. The plugin should:

  1. Identify .vue files: The plugin should recognize files ending with the .vue extension.

  2. Extract Component Definition: For each .vue file, extract the component's definition (including script, template, and style sections). Assume the .vue file structure is standard (i.e., <script setup>, <template>, <style>).

  3. Generate JavaScript Module: Create a JavaScript module that exports a function. This function should return a JavaScript object representing the Vue component definition. The object should have the following structure:

    {
      script: string; // The content of the <script> tag
      template: string; // The content of the <template> tag
      style: string[]; // An array of strings, each representing the content of a <style> tag
    }
    
  4. Handle Multiple Styles: The plugin must correctly handle multiple <style> tags within a .vue file.

  5. Preserve File Path: The plugin should preserve the original file path for debugging and error reporting.

Expected Behavior:

When a .vue file is encountered during the Rollup build process, the plugin should transform it into a JavaScript module that exports the component definition as described above. The resulting module should be compatible with Vue's component loading mechanism.

Edge Cases to Consider:

  • Empty <script>, <template>, or <style> tags.
  • .vue files that don't conform to the standard structure (though for simplicity, assume they do).
  • Files that are not .vue files should be ignored.

Examples

Example 1:

Input:  my-component.vue (content: `<template><div>Hello</div><style>h1 { color: blue; }</style><script>export default { data() { return { message: 'World' } } }</script>`)
Output:  A JavaScript module exporting:
{
  script: "export default { data() { return { message: 'World' } } }",
  template: "<div>Hello</div>",
  style: ["h1 { color: blue; }"]
}

Explanation: The plugin extracts the script, template, and style content and formats them into the expected JavaScript module.

Example 2:

Input: another-component.vue (content: `<template><h1>Component</h1></template><script setup></script>`)
Output: A JavaScript module exporting:
{
  script: "",
  template: "<h1>Component</h1>",
  style: []
}

Explanation: Handles a component with only a template and a <script setup> tag (empty script content).

Example 3:

Input:  component-with-multiple-styles.vue (content: `<template><div>Test</div></template><style>p { color: red; }</style><style>h2 { font-weight: bold; }</style><script>export default {}</script>`)
Output: A JavaScript module exporting:
{
  script: "export default {}",
  template: "<div>Test</div>",
  style: ["p { color: red; }", "h2 { font-weight: bold; }"]
}

Explanation: Correctly handles multiple <style> tags, returning them as an array.

Constraints

  • The plugin must be written in TypeScript.
  • The plugin should be compatible with Rollup v3.
  • The plugin should not introduce any external dependencies beyond those commonly available in a Node.js environment (e.g., fs, path).
  • The plugin should be reasonably performant; avoid unnecessary file I/O or complex string manipulations.
  • The plugin should handle file paths correctly, ensuring they are relative to the project root.

Notes

  • You'll need to use Rollup's plugin API to create the plugin. Refer to the Rollup documentation for details: https://rollupjs.org/docs/api/#plugin-api
  • Consider using a library like vue-template-compiler (though not strictly required) to parse the .vue file content more robustly. However, for this challenge, simple string manipulation is acceptable.
  • Focus on the core functionality of extracting the component definition and generating the JavaScript module. Error handling and advanced features can be omitted for brevity.
  • Think about how to use this.emitFile() to output the generated JavaScript module.
  • Start with a simple .vue file and gradually increase the complexity to test your plugin.
Loading editor...
typescript