Skip to content

Commit

Permalink
feat: simplify internals now that Vite adds CSS assets to the manifest
Browse files Browse the repository at this point in the history
Since vitejs/vite#8768 Vite will now add style
assets to the manifest preserving the original extension.
  • Loading branch information
ElMassimo committed Jul 1, 2022
1 parent c90bcba commit aa9c2b3
Show file tree
Hide file tree
Showing 4 changed files with 5 additions and 60 deletions.
28 changes: 3 additions & 25 deletions vite-plugin-ruby/src/config.ts
@@ -1,8 +1,8 @@
import { join, relative, resolve, isAbsolute } from 'path'
import { join, relative, resolve } from 'path'
import glob from 'fast-glob'

import type { UserConfig } from 'vite'
import { APP_ENV, ALL_ENVS_KEY, CSS_EXTENSIONS_REGEX, ENTRYPOINT_TYPES_REGEX } from './constants'
import { APP_ENV, ALL_ENVS_KEY, ENTRYPOINT_TYPES_REGEX } from './constants'
import { booleanOption, loadJsonConfig, configOptionFromEnv, slash } from './utils'
import { Config, ResolvedConfig, UnifiedConfig, MultiEnvConfig, Entrypoints } from './types'

Expand All @@ -11,9 +11,6 @@ export const defaultConfig: ResolvedConfig = loadJsonConfig(resolve(__dirname, '

// Internal: Returns the files defined in the entrypoints directory that should
// be processed by rollup.
//
// NOTE: For stylesheets the original extension is preserved in the name so that
// the resulting file can be accurately matched later in `extractChunkStylesheets`.
export function filterEntrypointsForRollup (entrypoints: Entrypoints): Entrypoints {
return entrypoints
.filter(([_name, filename]) => ENTRYPOINT_TYPES_REGEX.test(filename))
Expand All @@ -26,19 +23,6 @@ export function filterEntrypointAssets (entrypoints: Entrypoints): Entrypoints {
.filter(([_name, filename]) => !ENTRYPOINT_TYPES_REGEX.test(filename))
}

// Internal: Returns the style files defined in the entrypoints directory that
// are processed by Rollup but not included in the Vite.js manifest.
export function filterStylesheetAssets (entrypoints: Entrypoints): Entrypoints {
return entrypoints
.filter(([_name, filename]) => CSS_EXTENSIONS_REGEX.test(filename))
}

// Internal: Checks if the specified path is inside the specified dir.
function isInside (file: string, dir: string) {
const path = relative(dir, file)
return path && !path.startsWith('..') && !isAbsolute(path)
}

// Internal: Returns all files defined in the entrypoints directory.
export function resolveEntrypointFiles (projectRoot: string, sourceCodeDir: string, config: ResolvedConfig): Entrypoints {
const inputGlobs = config.ssrBuild
Expand All @@ -57,17 +41,11 @@ export function resolveEntrypointFiles (projectRoot: string, sourceCodeDir: stri
}

return entrypointFiles.map(filename => [
resolveEntryName(projectRoot, sourceCodeDir, filename),
relative(sourceCodeDir, filename),
filename,
])
}

// Internal: All entry names are relative to the sourceCodeDir if inside it, or
// to the project root if outside.
export function resolveEntryName (projectRoot: string, sourceCodeDir: string, file: string) {
return relative(isInside(file, sourceCodeDir) ? sourceCodeDir : projectRoot, file)
}

// Internal: Allows to use the `~` shorthand in the config globs.
export function resolveGlobs (projectRoot: string, sourceCodeDir: string, patterns: string[]) {
return patterns.map(pattern =>
Expand Down
4 changes: 0 additions & 4 deletions vite-plugin-ruby/src/constants.ts
Expand Up @@ -27,10 +27,6 @@ export const KNOWN_ENTRYPOINT_TYPES = [
...KNOWN_CSS_EXTENSIONS,
]

export const CSS_EXTENSIONS_REGEX = new RegExp(
`\\.(${KNOWN_CSS_EXTENSIONS.join('|')})$`,
)

export const ENTRYPOINT_TYPES_REGEX = new RegExp(
`\\.(${KNOWN_ENTRYPOINT_TYPES.join('|')})(\\?.*)?$`,
)
27 changes: 2 additions & 25 deletions vite-plugin-ruby/src/manifest.ts
Expand Up @@ -5,10 +5,9 @@ import createDebugger from 'debug'

import type { Plugin, ResolvedConfig } from 'vite'

import { OutputBundle, PluginContext } from 'rollup'
import type { OutputBundle, PluginContext } from 'rollup'
import { UnifiedConfig } from './types'
import { filterEntrypointAssets, filterStylesheetAssets } from './config'
import { withoutExtension } from './utils'
import { filterEntrypointAssets } from './config'

const debug = createDebugger('vite-plugin-ruby:assets-manifest')

Expand All @@ -29,26 +28,6 @@ export function assetsManifestPlugin (): Plugin {
let config: ResolvedConfig
let viteRubyConfig: UnifiedConfig

// Internal: For stylesheets Vite does not output the result to the manifest,
// so we extract the file name of the processed asset from the Rollup bundle.
function extractChunkStylesheets (bundle: OutputBundle, manifest: AssetsManifest) {
const cssFiles = Object.fromEntries(filterStylesheetAssets(viteRubyConfig.entrypoints))

Object.values(bundle).filter(chunk => chunk.type === 'asset' && chunk.name)
.forEach((chunk) => {
// Vite will output a single CSS chunk named style.css
if (!config.build.cssCodeSplit && chunk.name === 'style.css')
return manifest.set(chunk.name, { file: chunk.fileName, src: chunk.name })

// NOTE: Rollup appends `.css` to the file so it's removed before matching.
// See `filterEntrypointsForRollup`.
const src = withoutExtension(chunk.name!)
const absoluteFileName = cssFiles[src]
if (absoluteFileName)
manifest.set(path.relative(config.root, absoluteFileName), { file: chunk.fileName, src })
})
}

// Internal: Vite ignores some entrypoint assets, so we need to manually
// fingerprint the files and move them to the output directory.
async function fingerprintRemainingAssets (ctx: PluginContext, bundle: OutputBundle, manifest: AssetsManifest) {
Expand Down Expand Up @@ -82,8 +61,6 @@ export function assetsManifestPlugin (): Plugin {
if (!config.build.manifest) return

const manifest: AssetsManifest = new Map()
extractChunkStylesheets(bundle, manifest)

await fingerprintRemainingAssets(this, bundle, manifest)
debug({ manifest })

Expand Down
6 changes: 0 additions & 6 deletions vite-plugin-ruby/src/utils.ts
Expand Up @@ -30,12 +30,6 @@ export function booleanOption<T> (value: 'true' | 'false' | boolean | T): boolea
return value
}

// Internal: Returns the filename without the last extension.
export function withoutExtension (filename: string) {
const lastIndex = filename.lastIndexOf('.')
return lastIndex > -1 ? filename.substr(0, lastIndex) : filename
}

// Internal: Loads a json configuration file.
export function loadJsonConfig<T> (filepath: string): T {
return JSON.parse(readFileSync(filepath, { encoding: 'utf8', flag: 'r' })) as T
Expand Down

0 comments on commit aa9c2b3

Please sign in to comment.