Skip to content

Commit

Permalink
feat: ✨ add asset renderer decorators
Browse files Browse the repository at this point in the history
- the decorators remove the querystring from library assets with noquery attribute
  • Loading branch information
woldtwerk committed Oct 4, 2023
1 parent a3a8e11 commit 231099e
Show file tree
Hide file tree
Showing 8 changed files with 119 additions and 30 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace Drupal\uebertool_asset_renderer\Asset;

use Drupal\Core\Asset\AssetCollectionRendererInterface;

/**
* Optimizes a CSS asset.
*/
class CssCollectionRendererDecorator implements AssetCollectionRendererInterface {

public function __construct(protected AssetCollectionRendererInterface $prototype) {}

/**
* {@inheritdoc}
*/
public function render(array $css_assets) {
foreach ($css_assets as $css_asset) {
if (isset($css_asset['noquery'])) {
// Setting preprocessed to TRUE will prevent Drupal from prepending the querystring.
$css_asset['preprocessed'] = TRUE;
}
}

$elements = $this->prototype->render($css_assets);

return $elements;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace Drupal\uebertool_asset_renderer\Asset;

use Drupal\Core\Asset\AssetCollectionRendererInterface;

/**
* Optimizes a JS asset.
*/
class JsCollectionRendererDecorator implements AssetCollectionRendererInterface {

public function __construct(protected AssetCollectionRendererInterface $prototype) {}

/**
* {@inheritdoc}
*/
public function render(array $js_assets) {
foreach ($js_assets as $js_asset) {
if (isset($js_asset['noquery'])) {
// Setting preprocessed to TRUE will prevent Drupal from prepending the querystring.
$js_asset['preprocessed'] = TRUE;
}
}

$elements = $this->prototype->render($js_assets);

return $elements;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
name: UEbertool Asset Renderer
type: module
description: Remove version query from custom theme assets. Use noquery = true in your theme's libraries.yml.
package: UEbertool
core_version_requirement: ^9 || ^10
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
services:
uebertool_asset_renderer.js.collection_renderer:
class: Drupal\uebertool_asset_renderer\Asset\JsCollectionRendererDecorator
decorates: asset.js.collection_renderer
arguments: [ '@uebertool_asset_renderer.js.collection_renderer.inner' ]
uebertool_asset_renderer.css.collection_renderer:
class: Drupal\uebertool_asset_renderer\Asset\CssCollectionRendererDecorator
decorates: asset.css.collection_renderer
arguments: [ '@uebertool_asset_renderer.css.collection_renderer.inner' ]
58 changes: 33 additions & 25 deletions packages/vite-plugin-drupal/src/ce/ceLoader.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/**
* Common functionality for all loaders.
*/
export const common = (config: Record<string, any>) => `
export function common(config: Record<string, any>) {
return `
const cacheStringFunction = (fn) => {
const cache = Object.create(null)
Expand All @@ -22,12 +23,14 @@ const getTagName = (path) => {
return filename ? \`${config.prefix}-\${hyphenate(filename.replace(/\.(idle|visible|eager|lazy)\.ce\.(vue|tsx|jsx|ts|js)$/, ''))}\` : ''
}
`
}

/**
* Intersection Observer based loader for loading components when entering
* the viewport.
*/
export const visibleLoader = (modules: Record<string, any>) => `
export function visibleLoader(modules: Record<string, any>) {
return `
class CustomElementLoader {
#options
#modules
Expand Down Expand Up @@ -68,16 +71,16 @@ class CustomElementLoader {
if (entry.isIntersecting && tagname in this.#modules) {
if (this.#modules[tagname].path.match(/vue$/)) {
this.#modules[tagname].mod().then(async(mod) => {
const { defineCustomElement } = await import('@ueberbit/vite-plugin-drupal/ApiCustomElements')
customElements.define(tagname, defineCustomElement(mod.default))
try {
const { defineCustomElement } = await import('@ueberbit/vite-plugin-drupal/ApiCustomElements')
customElements.define(tagname, defineCustomElement(mod.default))
} catch(e) { console.log(e) }
})
} else {
this.#modules[tagname].mod().then(async(mod) => {
try {
customElements.define(tagname, mod[Object.keys(mod)[0]])
} catch(e) {
console.error(e)
}
} catch(e) { console.log(e) }
})
}
observer.disconnect()
Expand All @@ -97,12 +100,14 @@ Drupal.behaviors.customElementLoader = {
},
}
`
}

/**
* Lazy load components when the browser is idle.
* Requires polyfill for Safari.
*/
export const idleLoader = (modules: Record<string, any>) => `
export function idleLoader(modules: Record<string, any>) {
return `
const idleLoader = async () => {
const idleCE = ${modules}
Expand All @@ -116,9 +121,7 @@ const idleLoader = async () => {
const ce = await idleCE[path]()
try {
customElements.define(tagname, ce[Object.keys(ce)[0]])
} catch(e) {
console.error(e)
}
} catch(e) { console.log(e) }
}
}
}
Expand All @@ -133,11 +136,13 @@ if ('requestIdleCallback' in window) {
idleLoader()
}
`
}

/**
* Eagerly loads components.
*/
export const eagerLoader = (imports: string, modules: string, hasVue: boolean) => `
export function eagerLoader(imports: string, modules: string, hasVue: boolean) {
return `
${imports}
${modules.length > 2
? `
Expand All @@ -146,23 +151,27 @@ ${hasVue && 'import { defineCustomElement } from \'@ueberbit/vite-plugin-drupal/
const eagerCE = ${modules}
Object.keys(eagerCE).forEach(ce => {
${hasVue
? `
if(eagerCE[ce].type === 'vue') {
customElements.define(ce, defineCustomElement(eagerCE[ce].name))
} else {
customElements.define(ce, eagerCE[ce].name)
}
`
: 'customElements.define(ce, eagerCE[ce].name)'}
try {
${hasVue
? `
if(eagerCE[ce].type === 'vue') {
customElements.define(ce, defineCustomElement(eagerCE[ce].name))
} else {
customElements.define(ce, eagerCE[ce].name)
}
`
: 'customElements.define(ce, eagerCE[ce].name)'}
} catch(e) { console.log(e) }
})`
: ''}
`
}

/**
* Lazy loads components.
*/
export const lazyLoader = (modules: Record<string, any>) => `
export function lazyLoader(modules: Record<string, any>) {
return `
;(async () => {
const lazyCe = ${modules}
Expand All @@ -177,10 +186,9 @@ export const lazyLoader = (modules: Record<string, any>) => `
const ce = await lazyCe[path]()
try {
customElements.define(tagname, ce[Object.keys(ce)[0]])
} catch(e) {
console.error(e)
}
} catch(e) { console.log(e) }
}
}
})()
`
}
5 changes: 3 additions & 2 deletions packages/vite-plugin-drupal/src/plugins/breakpoints.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import process from 'node:process'
import fse from 'fs-extra'
import type { Plugin, ResolvedConfig } from 'vite'
import YAML from 'yaml'
Expand All @@ -12,7 +13,7 @@ import type { Context } from './context'
* @param size Breakpoint size.
* @returns Drupal Breakpoint entry.
*/
const getScreen = (theme: string, group: string, name: string, multipliers: string[], size?: number) => {
function getScreen(theme: string, group: string, name: string, multipliers: string[], size?: number) {
return {
[[theme, group, name].join('.')]: {
label: name,
Expand All @@ -28,7 +29,7 @@ const getScreen = (theme: string, group: string, name: string, multipliers: stri
}
}

const generateBreakpoints = async (theme: string, multipliers: string[]) => {
async function generateBreakpoints(theme: string, multipliers: string[]) {
let screens = {}
try {
const tailwindConfigFile = await import(`${process.cwd()}/tailwind.config.js`)
Expand Down
4 changes: 3 additions & 1 deletion packages/vite-plugin-drupal/src/plugins/config.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
/* eslint-disable @typescript-eslint/no-require-imports */
/* eslint-disable @typescript-eslint/no-var-requires */
import { basename, dirname, relative, resolve } from 'node:path'
import fs from 'node:fs'
import process from 'node:process'
import type { Plugin } from 'vite'
import { mergeConfig } from 'vite'
import fg from 'fast-glob'
import type { Context } from './context'

const postCssConfig = () => {
function postCssConfig() {
return fs.promises.access('postcss.config.js', fs.constants.F_OK)
.then(() => true)
.catch(() => false)
Expand Down
8 changes: 6 additions & 2 deletions packages/vite-plugin-drupal/src/plugins/libraries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export interface JSPart {
[key: string]: any
}
preprocess?: boolean
noquery?: boolean
}
}

Expand All @@ -38,6 +39,7 @@ export interface CSSPart {
media?: string
preprocess?: boolean
preprocessed?: boolean
noquery?: boolean
attributes?: Record<string, any>
}
}
Expand Down Expand Up @@ -152,7 +154,8 @@ function getCssPart(file: string, ctx: Context): DrupalLibrary {
[group]: {
[assetPath]: {
type: 'external',
preprocessed: true,
preprocess: false,
noquery: true,
attributes: {
...(file.match(/tailwind/)
? {
Expand Down Expand Up @@ -182,7 +185,8 @@ function getJsPart(file: string, ctx: Context): DrupalLibrary {
js: {
[assetPath]: {
type: ctx.dev ? 'external' : 'file',
preprocessed: true,
preprocess: false,
noquery: true,
minified: true,
attributes: { type: 'module', crossorigin: {} },
},
Expand Down

0 comments on commit 231099e

Please sign in to comment.