-
Notifications
You must be signed in to change notification settings - Fork 63
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
feat Adds Plugins feature #2563
base: main
Are you sure you want to change the base?
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎ 1 Skipped Deployment
|
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. |
39c2a61
to
bb8f5c0
Compare
cff672f
to
61a18b3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a couple of questions :)
packages/cli/src/utils/directory.ts
Outdated
* If it reaches process.cwd() (or /, as a safeguard), without finding it, it will throw an exception | ||
*/ | ||
const getCorePackagePath = () => { | ||
const coreFromNodeModules = path.join('node_modules', '@faststore', 'core') | ||
const packageFromNodeModules = path.join( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why was this variable renamed? If I understood correctly, most changes on this file are cosmetic (indentation) and you're adding the getPackagePath
entry to the returned object, right? If that's so can you undo the rename of this const
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good, it must have been a mistake. Renamed.
customDefinitions, | ||
primaryIdentifierForDefinitions | ||
) | ||
|
||
if (duplicates.length) { | ||
await confirmUserChoice(duplicates, fileName) | ||
if (newFilePath === customFilePath) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain this check here? I'm not getting the reason why.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Customization Files Array includes both Plugin Customization Files and User Customization Files. This check determines if the file is a User Customization File. If it is, the user is prompted to decide whether the file should be overwritten.
@@ -1,9 +1,15 @@ | |||
import WebFontsOverrides from 'src/customizations/src/components/overrides/WebFonts' | |||
import { default as CoreWebFonts } from 'src/fonts/WebFonts' | |||
import ThirdPartyScriptsOverrides from 'src/customizations/src/components/overrides/ThirdPartyScripts' | |||
import ThirdPartyScriptsPluginsOverrides from 'src/plugins/overrides/ThirdPartyScripts' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does B2B have any specific needs for Third Party Scripts or Web Fonts? Or has this just been added for consistency/completeness? If it's just for completeness, I'd remove it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need the WebFonts, but Third-Party Scripts are not required yet, so they have been removed.
@@ -0,0 +1,3 @@ | |||
// ---------------------------------------------------------- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Won't having a single plugins/index.scss
mean that if we have multiple plugins they will overwrite each other?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the styles will all be imported into this file and may override each other. We are taking care to keep all styles well-scoped within the plugin.
What's the purpose of this pull request?
Tip
PT-BR: Para melhor compreensão da feature recomenda-se assisti a apresentação feita ao time da Faststore Experience, explicando as motivações da feature e uma demo do seu funcionamento.
Note
This PR might seem extensive, but the majority of the changes are focused on the
hCMS.ts
andplugins.ts
files. The other files are mostly support files for the features and will have their content overwritten during thegenerate
process.This PR adds the plugin feature to Faststore.
The Faststore Plugins feature enables the addition of new functionalities to a store without requiring direct integration into the Faststore core or the store's source code. This approach not only maintains source code encapsulation but also extends the extensibility options already available in Faststore, such as Component Override, theming, and CMS customization, while introducing new capabilities.
Plugins operate as an intermediary layer between the Faststore core and the store code. This means that modifications made by a plugin override core functionality but can still be overridden by the store's customizations, ensuring flexibility and adaptability.
One notable enhancement brought by this feature is the ability to create new pages, something previously unsupported directly within the store. For instance, the Buyer Portal — a B2B solution — requires creating a management page and modifying existing Faststore components. With Plugins, such functionality can be implemented in a modular and scalable way, empowering developers to build solutions without impacting the core or existing store customizations.
The plugins feature is in the early stages of development and and plugins can only be developed by VTEX.
Implemented Features
How it works?
Configuring a New Plugin
To add custom functionalities to your Faststore store, you can create a new plugin. This plugin can include custom pages, UI components, themes, and CMS configurations, all in a modular way.
Plugin Package Structure
The plugin should follow this folder structure:
src/
: Contains the plugin source code, such as custom pages (pages/
), UI components (components/index.tsx
), and themes (theme/index.scss
). All content within src/ will be copied to the plugins/ folder inside.faststore
when the plugin is integrated into the store.cms/
: Contains configuration files for CMS integration, ascontent-types.json
andsections.json
.plugin.config.js
: The plugin configuration file where page paths are defined.Dependencies
You can add dependencies to your plugin, such as Faststore packages to access core and UI functionalities, as well as specific packages for the framework, such as Next.js 13, if required. These dependencies should be added to the plugin's package.json, enabling advanced features within the plugin code.
Creating a New Page
To create a new page in your plugin, you need to define its configuration in the
plugin.config.js
file. The configuration structure should look similar to the example below:Key Properties:
"my-account"
is the name of the page, and this should match the name of the file in the pages/ folder (e.g.,my-account.tsx
).path
: This defines the route where the page will be registered. It follows the same pattern as the Next.js page router, meaning the page will be accessible via the defined path (e.g.,/my-account
).appLayout
: This property defines whether the global components (like the header and footer) will be displayed on the page. Set it to false to disable the default layout.Page Structure
Each page should have at least the following structure. The loader function will be executed server-side:
Creating New Sections and Overriding Existing Sections
To create new sections or override existing ones, you should follow a structure similar to the one used in Faststore stores. The sections should be placed inside the /components folder and the index.tsx file must export all your sections as an object, with each section as a property of that object
Section Structure
The new sections will be made available, and any sections with the same name as the core sections will override those sections.
Here's an example of how to define sections in an index.tsx file:
In this example:
Customizing CMS via Plugin
To customize the CMS via a plugin, you need to create two files: sections.json and content-types.json. These files should be placed under the
/cms/faststore/
folder in your plugin.File Structure:
sections.json
: Defines the sections available in the plugin.content-types.json
: Defines the content types handled by the plugin.Merging Files
To merge your plugin’s CMS files with the store’s files, use the
cms-sync
command. This will merge the plugin’ssections.json
andcontent-types.json
with the store’s, giving priority to the store's content.This command ensures that:
Creating a Theme
To create a theme for your plugin, the process is similar to creating a theme for a store. The theme should be defined in the
src/themes/index.scss
file, where all the CSS for the plugin will be written.File Structure:
index.scss
: This is where all the styles for the plugin should be defined.CSS Loading Order
The CSS from the plugin's
index.scss
will be loaded after the global styles and before the store's CSS, allowing it to override the store's styles while respecting the global styles.Adding a Plugin to the Store
To add a plugin to your store, you need to follow these steps:
1. Install the Plugin Package
First, install the plugin package in the store’s codebase. For example, if you are adding the @faststore/plugin-test, run:
2. Update discovery.config.js
In the discovery.config.js file, add the plugin name to the plugins property. This will register the plugin for use in the store.
3. Configure Plugin Page Paths (Optional)
You can also configure the path for the plugin's pages in the discovery.config.js file. For example, to change the default path for the my-account page, use the following structure:
This allows you to specify custom paths for any pages defined by the plugin.
How to test it?
Testing Locally
To test your plugin locally, you need to link the core package, CLI, and the plugin to a starter store. Here's how you can do it:
1. Link the Core, CLI, and Plugin Packages
First, you will need to link the core, CLI, and the plugin to your local starter store. You can do this using yarn link for each package to the starter from this PR.
Link the core and CLI from the current PR
Link the plugin from this repository.
2. Run the Starter Store
Once linked, navigate to the starter store's directory and run the commands as you normally would in a store:
Every time you make a change to the plugin, you will need to restart the server for the changes to take effect.
For changes made to the core and CLI, ensure they are rebuilt before testing:
Starters Deploy Preview
Testing on Preview
To test your plugin on the preview environment, follow these steps:
1. Preview the Starter Store with Plugins
There is an open PR that allows you to preview the store with plugins running. You can access the preview environment using the following link:
Preview Store
This preview is based on the starter store from the PR starter.store/pull/616.
2. Check the Main Color Override
On the homepage, you will notice that the main color has been overridden by red, which is done via the plugin. This demonstrates that the plugin is successfully applying styles to the store.
3. Test the my-account Page
You can access the my-account page by navigating to /my-account in the preview store. On this page, you will see the result of the useSession hook displayed in blue.
My Account
4. Test the Product Detail Page (PDP)
On the Product Detail Page (PDP), you will see the overridden component from the plugin. This component displays:
The result of the useSession hook.
A Next.js link to navigate back to the homepage.
You can test this by visiting a PDP, such as:
Product Detail Page
References
B2BTEAM-1951
starter.store/pull/616.
Preview Store
POC-Plugin
Checklist
You may erase this after checking them all 😉
PR Title and Commit Messages
feat
,fix
,chore
,docs
,style
,refactor
andtest
PR Description
breaking change
,bug
,contributing
,performance
,documentation
..Dependencies
yarn.lock
file when there were changes to the packages