Skip to content

Commit

Permalink
enh: Allow sharing JavaScript modules across apps and core
Browse files Browse the repository at this point in the history
Initially `vue` and `@nextcloud/vue` are shared by server core.

Signed-off-by: Ferdinand Thiessen <[email protected]>
  • Loading branch information
susnux committed Feb 13, 2024
1 parent 2972447 commit 3e58a94
Show file tree
Hide file tree
Showing 8 changed files with 57 additions and 3 deletions.
4 changes: 4 additions & 0 deletions core/Listener/BeforeTemplateRenderedListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ public function handle(Event $event): void {
return;
}

// Modules we share everywhere
Util::addSharedModule('core', 'shared-vue', 'vue');
Util::addSharedModule('core', 'shared-nextcloud-vue', '@nextcloud/vue');

if ($event->getResponse()->getRenderAs() === TemplateResponse::RENDER_AS_USER) {
// Making sure to inject just after core
Util::addScript('core', 'unsupported-browser-redirect');
Expand Down
1 change: 1 addition & 0 deletions core/src/modules/nextcloud-vue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from '@nextcloud/vue'
4 changes: 4 additions & 0 deletions core/src/modules/vue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import Vue from 'vue'

export * from 'vue'
export default Vue
8 changes: 8 additions & 0 deletions lib/private/TemplateLayout.php
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,14 @@ public function __construct($renderAs, $appId = '') {
$this->append('jsfiles', $web.'/'.$file . $this->getVersionHashSuffix());
}

$jsModules = array_map(function (string $path) {
$info = end(self::findJavascriptFiles([$path]));
$web = $info[1];
$file = $info[2];
return $web . '/' . $file . $this->getVersionHashSuffix();
}, Util::getSharedModules());
$this->assign('jsmodules', $jsModules);

try {
$pathInfo = \OC::$server->getRequest()->getPathInfo();
} catch (\Exception $e) {
Expand Down
9 changes: 7 additions & 2 deletions lib/private/legacy/template/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,10 @@ function emit_script_tag(string $src, string $script_content = '', string $conte
$defer_str = ' defer';
$type = $content_type !== '' ? ' type="' . $content_type . '"' : '';

$s = '<script nonce="' . $nonceManager->getNonce() . '"';
$s = '<script nonce="' . $nonceManager->getNonce() . '"' . $type;
if (!empty($src)) {
// emit script tag for deferred loading from $src
$s .= $defer_str.' src="' . $src .'"' . $type . '>';
$s .= $defer_str.' src="' . $src .'">';
} elseif ($script_content !== '') {
// emit script tag for inline script from $script_content without defer (see MDN)
$s .= ">\n".$script_content."\n";
Expand All @@ -100,11 +100,16 @@ function emit_script_tag(string $src, string $script_content = '', string $conte
* @param array $obj all the script information from template
*/
function emit_script_loading_tags($obj) {
if (!empty($obj['jsmodules'])) {
emit_script_tag('', json_encode(['imports' => $obj['jsmodules']]), 'importmap');
}

foreach ($obj['jsfiles'] as $jsfile) {
$fileName = explode('?', $jsfile, 2)[0];
$type = str_ends_with($fileName, '.mjs') ? 'module' : '';
emit_script_tag($jsfile, '', $type);
}

if (!empty($obj['inline_ocjs'])) {
emit_script_tag('', $obj['inline_ocjs']);
}
Expand Down
29 changes: 29 additions & 0 deletions lib/public/Util.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ class Util {
private static array $scriptsInit = [];
private static array $scripts = [];
private static array $scriptDeps = [];
private static array $sharedModules = [];

/**
* get the current installed version of Nextcloud
Expand Down Expand Up @@ -206,6 +207,34 @@ public static function addScript(string $application, string $file = null, strin
}
}

/**
* Provide a shared JavaScript module
* Apps - if using this - should only provide their own API packages not external dependencies as this can conflict with server core.
*
* @param string $application The application where to look for the entry point (see `addScript`)
* @param string $file The JavaScript entry point file name (see `addScript`)
* @param string $module The modul name
* @since 29.0.0
*/
public static function addSharedModule(string $application, string $file, string $module): void {
if (!empty($application)) {
$path = "$application/js/$file";
} else {
$path = "js/$file";
}

self::$sharedModules[$module] = $path;
}

/**
* Get all shared JavaScript modules
*
* @since 29.0.0
*/
public static function getSharedModules(): array {
return self::$sharedModules;
}

/**
* Return the list of scripts injected to the page
*
Expand Down
4 changes: 3 additions & 1 deletion server.modules.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
import { dirname, join } from 'path'
import { fileURLToPath } from 'url'

const __dirname = import.meta.dirname ?? dirname(fileURLToPath(import.meta.url))
const __dirname = globalThis?.__dirname ?? import.meta.dirname ?? dirname(fileURLToPath(import.meta.url))

export default {
comments: {
Expand All @@ -32,6 +32,8 @@ export default {
init: join(__dirname, 'apps/comments/src', 'init.ts'),
},
core: {
'shared-vue': join(__dirname, 'core/src', 'modules/vue.ts'),
'shared-nextcloud-vue': join(__dirname, 'core/src', 'modules/nextcloud-vue.ts'),
backgroundjobs: join(__dirname, 'core/src', 'cron.ts'),
files_client: join(__dirname, 'core/src', 'files/client.js'),
files_fileinfo: join(__dirname, 'core/src', 'files/fileinfo.js'),
Expand Down
1 change: 1 addition & 0 deletions vite.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export default createAppConfig(
build: {
cssCodeSplit: false,
rollupOptions: {
preserveEntrySignatures: 'allow-extension',
output: {
chunkFileNames: (info) => info.name.match(/core-common/) ? 'dist/core-common.mjs' : 'dist/chunks/[name]-[hash].mjs',
entryFileNames: 'dist/[name].mjs',
Expand Down

0 comments on commit 3e58a94

Please sign in to comment.