Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Surprising output in rollup bundle sourcemaps for none .js entrypoint files #358

Open
2 tasks done
joekrump opened this issue Apr 24, 2023 · 2 comments
Open
2 tasks done
Labels
bug Something isn't working

Comments

@joekrump
Copy link

joekrump commented Apr 24, 2023

  • I have tried upgrading by running bundle update vite_ruby.
  • I have read the troubleshooting section before opening an issue.

Description 📖

I'm wondering if this might be a bug that results from this:

entryFileNames: ssrBuild ? undefined : outputFileName('js'),

When enabling sourcemaps, and running a build via bin/vite build or rails assets:precompile, if I write a rollup plugin to inspect the sourcemap files, I see that a sourcemap entry exists for a .sass file that I have as an entry point, even though no such file exists in the actual build output. Also I see that the filename for the sass has a .js extension which seems strange.

Reproduction 🐞

  1. In the app/frontend/entrypoints directory, include at least one .sass file. Ex.

image

  1. Include at least one of the sass files on a .html.erb page in the app. Ex.
vite_stylesheet_tag('quill.sass', media: 'all')
  1. Add the following test rollupPlugin code to your vite.config.ts

Rollup plugin code

function isSourcemap(file) {
  return file.type === 'asset' && file.fileName.endsWith('.js.map');
}

function extractSourcemapDataFromBundle(_outputOptions, bundle) {
  const sourceMaps = Object.values(bundle).filter(isSourcemap);

  return sourceMaps.map((sourcemap) => {
    console.info(JSON.parse(sourcemap.source));
  });
}

export function exampleRollupPlugin() {
  return {
    name: 'sourcemap-reader',
    writeBundle: {
      async handler(outputOptions, bundle) {
        extractSourcemapDataFromBundle(outputOptions, bundle);
      },
    },
  };
}
  1. Include it in your vite.config.ts file and make sure you have sourcemaps enabled:

vite.config.ts

import { defineConfig } from 'vite';
import rubyPlugin from 'vite-plugin-ruby';

export default defineConfig({
  build: {
    sourcemap: true,
    rollupOptions: {
      plugins: exampleRollupPlugin,
    },
  },
  plugins: [rubyPlugin()],
});
  1. run bin/vite build

In your console output you will see something like:

{
  version: 3,
  file: 'quill-14abea49.js',
  sources: [],
  sourcesContent: [],
  names: [],
  mappings: ''
}

What's surprising here is that the file is a .js file! Also note that most of the properties are empty values since the source is not actually a .js file. It's the quill.sass file.

ℹ️ In the example screenshot of my entrypoints posted on reproduction Step 1 (above), you can see that I have a quill.js and quill.sass file. The output above is for the quill.sass entry file. The quill.js entrypoint's bundle sourcemap Object is what is expected. Something like this:

{
  version: 3,
  file: 'quill-5b69f169.js',
  sources: [
    '../../../node_modules/quill/dist/quill.js',
    '../../../node_modules/quill-paste-smart/dist/quill-paste-smart.js',
    '../../../node_modules/quill-mention/dist/quill.mention.esm.js',
    '../../../app/frontend/entrypoints/quill.js'
  ],
  sourcesContent: [
    '/*!\n' +
      ' * Quill Editor v1.3.7\n' +
      ' * https://quilljs.com/\n' +
      ' * Copyright (c) 2014, Jason Chen\n' +
      ' * Copyright (c) 2013, salesforce.com\n' +
      ' */\n' +
      '(function webpackUniversalModuleDefinition(root, factory) {\n' +
      "\tif(typeof exports === 'object' && typeof module === 'object')\n" +
      '\t\tmodule.exports = factory();\n' +
      "\telse if(typeof define === 'function' && define.amd)\n" +
      '\t\tdefine([], factory);\n' +
      "\telse if(typeof exports === 'object')\n" +
      '\t\texports["Quill"] = factory();\n' +
      '\telse\n' +
      '\t\troot["Quill"] = factory();\n' +
      "})(typeof self !== 'undefined' ? self : this, function() {\n" +
      'return /******/ (function(modules) { // webpackBootstrap\n' +
      'REDACTED FOR BEVITY'
    ],
    names: ['REDACTED FOR BEVITY'],
    mappings: 'REDACTED FOR BEVITY'
  }
}
Vite Ruby Info

Run bin/rake vite:info and provide the output:

Running via Spring preloader in process 13157
bin/vite present?: true
vite_ruby: 3.2.10
vite_rails: 3.0.12
rails: 6.1.7.3
node: v18.12.1
npm: 8.19.2
yarn: 1.22.19
pnpm: 
ruby: ruby 3.0.6p216 (2023-03-30 revision 23a532679b) [arm64-darwin22]

installed packages:
internal-hackathons@0.1.0 /Users/josephkrump/code/projects/internal_hackathons
├─┬ @vitejs/plugin-vue@3.1.0
│ └── vite@3.2.3 deduped
├─┬ vite-plugin-full-reload@1.0.4
│ └── vite@3.2.3 deduped
├─┬ vite-plugin-ruby@3.1.2
│ └── vite@3.2.3 deduped
├── vite@3.2.3
└─┬ vitest@0.27.3
  ├─┬ vite-node@0.27.3
  │ └── vite@4.2.1
  └── vite@4.2.1

Screenshots 📷

Provide console or browser screenshots of the problem.

@joekrump
Copy link
Author

joekrump commented Apr 25, 2023

So I was able to apply a fix locally that worked for this case as a proof of concept.

function outputOptions (assetsDir: string, ssrBuild: boolean) {
// Internal: Avoid nesting entrypoints unnecessarily.
const outputFileName = (ext: string) => ({ name }: { name: string }) => {
const shortName = basename(name).split('.')[0]
return posix.join(assetsDir, `${shortName}-[hash].${ext}`)
}
return {
entryFileNames: ssrBuild ? undefined : outputFileName('js'),
}
}

Changed to:

function outputOptions (assetsDir, ssrBuild) {
  const outputFileName = (ext) => ({ name }) => {
    const shortName = basename(name).split('.')[0] 
    
    let indexOfDot = name.lastIndexOf(".");
    if (indexOfDot > -1) {
      let extension = name.substring(indexOfDot + 1, name.length);

      if (ext !== extension && extension === "sass") {
        extension = "css";
      }
      ext = extension;
    }

    return posix.join(assetsDir, `${shortName}-[hash].${ext}`)
  };
  return {
    entryFileNames: ssrBuild ? undefined : outputFileName('js'),
  };
}

@ElMassimo ElMassimo added bug Something isn't working and removed bug: pending triage Something doesn't seem to be working, but hasn't been verified labels May 3, 2023
@ElMassimo
Copy link
Owner

ElMassimo commented May 3, 2023

Hi Joe!

Thanks for providing a detailed report.

It's likely that outputOptions should have been updated after Vite 3 started correctly processing stylesheets as entrypoints (vitejs/vite#6649 and vitejs/vite#8768), as now it's possible for entryFileNames to have a .css extension.

We should probably let Rollup do its thing by using [hash].[ext] instead of trying to infer the extension, but need to check whether that works for all scenarios and pre-processors (or perhaps it doesn't even work in entryFileNames).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants