Releases: Jahia/javascript-modules
JavaScript Modules v0.7.0 ☕️
This release adds support for JS<->Java interactions through OSGi services.
New Features
-
JS code can interact with Java code through OSGi services. Usage looks roughly like this:
import { jahiaComponent, server } from "@jahia/javascript-modules-library"; jahiaComponent( { nodeType: "javascriptExample:testOSGi", name: "default", componentType: "view", }, () => <p>{server.osgi.getService("org.example.services.SimpleService").sayHello("World")}</p>, );
The documentation will be updated shortly with more details on how to use this feature. In the meantime, you can check #294 for more examples. If you have feedback on this feature, please reach out to us: calendar.app.google/LigWTiUSDeHmVCwa7
-
JS client files are now minified. This should save up to 1 MB of client-side JavaScript for cold page loads! #269
-
process.env.NODE_ENVis now replaced during the build. This change makes JavaScript Modules more compatible with the rest of the Node.js ecosystem. #263 -
Sourcemaps are generated by default in development mode. #272
Breaking Changes
buildNavMenuhas been removed. #282
Dependency Updates (#299)
All runtime dependencies have been updated to the latest versions. This includes:
i18next: 23.10.1 → 25.0.2 (🚨 Check i18next.com/misc/migration-guide for breaking changes affecting you)react: 19.0.0 → 19.1.0react-i18next: 15.4.0 → 15.5.1styled-jsx: 5.1.6 → 5.1.7
Other Changes
- All packages of this monorepo are now published to maven/npmjs.com on every commit. You can check the versions tab to install pre-release versions. Be careful, pre-releases do not go through our QA step. #254 and #281
- You should no longer experience issues with jExperience and page-level personalization. #295
- GraalVM is now correctly detected. #293
Full Changelog: 0_6_1...0_7_0
JavaScript Modules v0.6.1
JavaScript Modules are not compatible with Jahia 8.2.0.x.
This releases enforces that by raising the minimum Jahia version to 8.2.1.0.
JavaScript Modules v0.6.0 📖
The new documentation is here! We have completely rewritten the Getting Started guide, read it here.
This release contains new and improved APIs in @jahia/javascript-modules-library. Some of these changes are breaking.
Breaking Changes
Removed useUrlBuilder (#198)
This API was verbose and cumbersome, so we removed the intermediate steps needed to produce a URL out of a node, a module file or an endpoint.
-
To get the URL of a JCR node:
-import { useUrlBuilder } from "@jahia/javascript-modules-library"; -const { buildNodeUrl } = useUrlBuilder(); -const url = buildNodeUrl({ nodePath: currentNode.getPath() }); +import { buildNodeUrl } from "@jahia/javascript-modules-library"; +const url = buildNodeUrl(currentNode);
Additional parameters (e.g.
language,mode), can be given as a second object parameterbuildNodeUrl(currentNode, { language: "en_US", mode: "edit" }) -
To get the URL of a file exposed by a module:
-import { useUrlBuilder } from "@jahia/javascript-modules-library"; -const { buildStaticUrl } = useUrlBuilder(); -const url = buildStaticUrl({ assetPath: "../dist/style.css" }); +import { buildModuleFileUrl } from "@jahia/javascript-modules-library"; +const url = buildModuleFileUrl("dist/style.css");
Make sure the path is made available in
package.json>jahia>static-resources.Path is no longer resolved from
<module>/static, but from<module>. You may change the module withbuildModuleFileUrl("dist/style.css", { moduleName: "other-module" }). -
To get the URL of a Jahia endpoint:
-import { buildUrl } from "@jahia/javascript-modules-library"; -const liveUrl = buildUrl({ value: renderContext.getURLGenerator().getLive() }, renderContext, currentResource); +import { buildEndpointUrl } from "@jahia/javascript-modules-library"; +const liveUrl = buildEndpointUrl(renderContext.getURLGenerator().getLive());
editable was changed to readOnly (#187)
In <Render> and <Area>, use readOnly instead of editable={false} to prevent the children from being editable.
limitedAbsoluteAreaEdit={true} is now readOnly="children".
getNodeFromPathOrId was removed (#189)
Use session.getNode(<path>) and session.getNodeByIdentifier(<id>) instead.
Changed <Area> and <AbsoluteArea> parameters (#199)
- Replaced
pathandlevelparameters of<AbsoluteArea>withparent, which expects a JCR node. - Removed
pathandareaAsSubNodeof<Area>, use<AbsoluteArea parent={currentNode/session.getNode(path)} />instead.
Some arguments have been renamed: areaView -> view, allowedTypes -> allowedNodeTypes, areaType -> nodeType.
New features
Added getSiteLocales() (#189)
This function produces a record (JS plain object), whose keys are language codes (e.g. en_US), mapped to a locale. Building a language-switcher should be easier and less error-prone with this new API:
<ul>
{Object.entries(getSiteLocales()).map(([language, locale]) => (
<li key={language}>
<a
href={buildNodeUrl(mainNode, { language })}
aria-current={language === currentResource.getLocale().toString() ? "page" : undefined}
>
{locale.getDisplayLanguage(locale)}
</a>
</li>
))}
</ul>Added <RenderChild> and <RenderChildren> (#190)
These two components make rendering respectively a single child node, many children nodes easier and less verbose.
-{currentNode.hasNode(name) ? <Render node={currentNode.getNode(name}} : <AddContentButtons />}
+<RenderChild name={name} />-{getChildNodes(currentNode, -1).map((node) => (
- <Render key={node.getIdentifier()} node={node} />
-))}
-<AddContentButtons />
+<RenderChildren />Added priority to jahiaComponent (#213)
The first argument of jahiaComponent now accepts an additional setting: priority. This will come in handy when you have views or templates for mixins and you want to make sure the right one is rendered when several can be rendered.
jahiaComponent(
{
componentType: "view",
nodeType: "nsmix:mixin",
priority: 10, // Non-default priority value (default is 0), this view will be picked if no higher priority view matches a node
},
() => <p>Render me!</p>,
);It's an integer working roughly like CSS z-index: the biggest integer wins. You can also use an negative integer to create a "fallback" view or template, that is, a view or template only used if there is no better match. The default value is 0.
Windows is now officially supported (#196)
You should now be able to develop JavaScript Modules in Windows without any issues. If that's not the case, please reach out to us.
Deprecations
buildNavMenuis now deprecated and will be removed in the future. This function has complexity and performance issues, and is too complex for simple needs, too simple for complex needs. We now recommend you build your navigation menu by iterating over JCR nodes.
Full Changelog: 0_5_6...0_6_0
JavaScript Modules v0.5.6
New features
This release introduces the ability to place <HydrateInBrowser> anywhere in the component tree, not only as a leaf as it used to be. In practice, this means that <HydrateInBrowser> now accepts children, and they'll be rendered server-side!
// default.server.tsx
jahiaComponent(
{
componentType: "view",
nodeType: "example:Component",
displayName: "Example Component"
},
({ title }: { title: string }) => {
return (
<HydrateInBrowser child={HydratedComponent} props={{ title }}>
<p>I'm rendered on the server</p>
{/* You can place server-only code here, like <Render> components */}
</HydrateInBrowser>
)
}
);
// HydratedComponent.client.tsx
export default function HydratedComponent({title, children}: { title: string; children: React.ReactNode }) {
// This component can contain client-only code: useState, useEffect...
return (
<article>
<h1>{title}</h1>
{/* Server-rendered content will be inserted here: */}
{children}
</article>
)
}There's one small gotcha with our implementation for now: we insert a <div> element to create a hydration boundary. This a related to a React limitation and we haven't found a way around it yet. If this is an issue for your use cases, please let us know.
If you add children to <RenderInBrowser>, they'll be used as a placeholder until client-side rendering takes over. It can be used like this:
jahiaComponent(
{
componentType: "view",
nodeType: "example:Component",
displayName: "Example Component"
},
({ place }: { place: string }) => {
return (
<RenderInBrowser child={MapComponent} props={{ place }}>
<p>The map is loading, please wait...</p>
</RenderInBrowser>
)
}
);We also added support for all export default statements, no only export default function. (#151)
Full Changelog: 0_5_5...0_5_6
JavaScript Modules v0.5.5
What's Changed
Other Changes
- build: Release and version test module alongside the monorepo by @baptistegrimaud in #138
- chore: use a single sync-version.js by @baptistegrimaud in #143
Full Changelog: 0_5_4...0_5_5
JavaScript Modules v0.5.4 👋
Hello World! 👋
We updated the Hello World template (npm init @jahia/module) to mirror our recent changes regarding the build environment: JavaScript Modules v0.5.1 ⚡️
Here is what you should expect after creating a new module:
It promotes all the practices we now consider as "best practices":
- Single folder components (define JSX, CSS and CND in the same folder)
- CSS modules
- Internationalized website
- Typed JSX (TSX)
- Tooling: Prettier & ESLint
We also fixed a few bugs in @jahia/vite-plugin:
- Vite should bundle all dependencies in SRR mode in #142
- Improved treeshaking and simpler client output in #145
Full Changelog: 0_5_3...0_5_4
JavaScript Modules v0.5.3
What's Changed
- feat: Integrate @jahia/create-module into the monorepo to follow the same versioning by @baptistegrimaud in #116
- fix(vite-plugin): skip client build if it has no entry files by @GauBen in #126
- feat: Use Vite in the template by @baptistegrimaud in #124
- ci: special documentation ci by @GauBen in #127
- build(create-module): Rename package to @jahia/create-module by @baptistegrimaud in #131
Full Changelog: 0_5_1...0_5_3
JavaScript Modules v0.5.1 ⚡️
Welcome Vite! ⚡️
This release is a fairly large release with a major architectural rewrite on our end. This means a lot of breaking changes on your end too (sorry about that) but that's for the best: we replaced Webpack with Vite.
We heard your feedback about Webpack and decided to solve it by removing it altogether. If you're not familiar with Vite (and Webpack btw), it's a bundler: it takes source code in various languages (JS, TS, CSS, SCSS...) and produces a coherent output that the runtime can understand (e.g. JS+CSS for the browser).
All your configuration needs should be handled by a newcomer in this repository: @jahia/vite-plugin. It's a Vite plugin that takes care of everything for you:
import { defineConfig } from 'vite'
import jahia from '@jahia/vite-plugin'
export default defineConfig({
plugins: [
// ✨ And voilà!
jahia()
]
})There's no migration guide to migrate from Webpack to Vite—there's too much to cover—so instead we offer you a migration session with our Developer Advocate, @GauBen: → Book an appointment
Changelog
- Build your JavaScript Modules with Vite and enjoy all its features out of the box: TypeScript transpilation, CSS Modules, raw imports, CSS preprocessors...
- @jahia/javascript-modules-library is now written in TypeScript, with slightly stricter types, helping you find bugs before even running your code. As far as you're concerned, it's only a typing library, its runtime is handled by the JavaScript Modules Engine.
- React 19! We bumped the supported React version and enabled support for the modern JSX transform.
- The client directory (
src/client) no longer needs to be flat, you can nest and organize your components the way you like. - Hydration now supports a larger range of objects: your props can be
Map,Set,Dateobjects and more. <AddContentButtons />now takes a list of node types:<AddContentButtons nodeTypes={['ns:text', 'ns:richText']} />- Registering your components is now simpler, we added a
jahiaComponentfunction that takes care of both the declaration (formerlydefineJahiaComponent) and the registration (formerlyregisterJahiaComponents):jahiaComponent( { nodeType: "ns:foobar", displayName: "My fancy content type", componentType: "view", }, ({ foo, bar }, { currentNode }) => { // ^^^ props ^^^ server context return ( <p> {foo} {bar} <a href={currentNode.getUrl()}>Read more</a> </p> ); }, );
- Our Vite plugin supports glob entrypoints, allowing you to get rid of all the
export * from ...statements - Under the hood, as we completely removed Webpack for both frontend and backend code, we no longer use Webpack Module Federation. Instead, we leverage a standard JS feature:
<script type="importmap">. If you want to support old web browsers (see unsupported browsers), you'll have to add es-module-shims to your Jahia instance.
All changes: 0_4_0...0_5_1
javascript-modules-0.4.0
What's Changed
Other Changes
- ci : fix manual workflow for release by @ksagnard in #35
- build(test): Updated to the latest version of jahia/cypress by @Fgerthoffert in #37
- chore: sync files with
Jahia/.github[skip ci] by @jahia-ci in #40 - chore: sync files with
Jahia/.github[skip ci] by @jahia-ci in #42 - chore: sync files with
Jahia/.github[skip ci] by @jahia-ci in #43 - style: removed barrel files by @GauBen in #45
- refactor: migrate render components to typescript by @GauBen in #47
- refactor: migrate jahia components to typescript by @GauBen in #48
- docs: Remove Shields images in README by @baptistegrimaud in #15
- feat: Add javascript-modules-engine as Jahia-Depends by @baptistegrimaud in #28
- build: add scripts to the mono repository by @baptistegrimaud in #44
- build(test): Bump @jahia/cypress from 4.0.0 to 4.1.0 by @dependabot in #41
New Contributors
- @ksagnard made their first contribution in #35
- @dependabot made their first contribution in #41
Full Changelog: 0_3_0...0_4_0
javascript-modules-0.3.0
0_3_0 [skip ci] [maven-release-plugin]copy for tag 0_3_0
