Creating your own custom workspace generators allows you to quickly ramp up complete projects according to your standards. The Workspace is the key part that controls your component-workflow and where your components are managed. Standardizing it can help with onboarding and delivery of new apps and components.
Use the base workspace generator template followed by the name you want to give your generator.
For example:
bit create workspace-generator my-workspace
1 component(s) were created company.scope/my-workspace location: scope/my-workspace env: teambit.harmony/aspect
This will give you a collection of files inside the my-workspace namespace, as below:
├── index.ts ├── my-workspace.aspect.ts ├── my-workspace.docs.mdx ├── my-workspace.main.runtime.ts └── template ├── files │ ├── git-ignore.ts │ ├── readme-file.ts │ └── workspace-config.ts └── index.ts
In the templates folder we have a folder of files that will get generated such as the git-ignore and readme file which can be modified to how you like. The workspace-config file is how you can configure your workspace, more on this later. The index file is the one that registers all these files with the correct name, path and which contents to return.
generateFiles: async (context: WorkspaceContext) => { return [ { relativePath: 'workspace.jsonc', content: await workspaceConfig(context) }, { relativePath: '.gitignore', content: gitIgnore() }, { relativePath: 'README.md', content: readme() } ]; },
In this file you will also see an array of components that you can add to be generated in your workspace. You can import any component here for developers to modify it to their liking. In the generated workspace the component will no longer be tied to the scope we are cloning it from.
importComponents: () => { return [ { id: 'learn-bit-react.ecommerce/entity/product', path: 'ecommerce/entity/product', }, ]; };
We can also change the name of our template and description:
export const workspaceTemplate: WorkspaceTemplate = { name: 'learn-bit-workspace', description: 'workspace template for learn bit',
We are now ready to modify our template and we can test it out by adding something very simple to see if it works.
Let's modify the readme to include a new line at the top:
export function readme() { return `hello world from my workspace generator`; }
As we have modified our generator we will need to compile it:
bit compile
Now if we use our generator to generate a new workspace we will get one with our custom text in the ReadMe. We want to test this locally and not export our workspace template yet as we are still developing it.
Open a new terminal window separate from this workspace and run the following command:
bit new <templateName> <workspaceName> --load-from <localProjectPath> --aspect <workspaceGeneratorID>
- The
<templateName>is taken from the name in the template index file. It can be changed to anything you like. If you do change it just remember to runbit compilebefore using it. - The
<workspaceName>is the name you want to call your workspace - The
<localProjectPath>is where the path is to the project that holds the template generator. Typepwdin the terminal to get the correct path. <workspaceGeneratorID>is the id of the workspace generator
For example, the command may look like this:
bit new learn-bit-workspace sports-store --load-from /Users/me/path/to/this/dir --aspect learn-bit-react.base-ui/workspace-generator
This will now create a new workspace for us in the directory sports-store.
cd sports-store
If we open the sports-store directory it in our editor and inspect it we will see the custom message we added in the readMe file.
Once we have finished all customizations and our generator is ready to be exported for other teams to use, we can then tag a new version of this component and export it to our organization's repo.
bit tag --all --message "my workspace generator"
Once tagging has finished, you can export it to your remote scope.
bit export
Once it has been exported, you can now generate a new workspace with the following:
bit new<templateName><workspaceName>--aspectflag- your full
<workspaceGeneratorID>
Example:
bit new learn-bit-workspace shoe-store --aspect learn-bit-react.base-ui/workspace-generator
Now we are ready to put this to use. The workspace.json file is the file we will configure the most, as this will set up our workspace for all projects across our organization. We want different teams to own different features and have their own workspaces but we want to have standards across all of them and this is how we can do it.
You are able to configure anything you want. For now, let's take a look at some example of things we can configure.
Put your team's logo in the workspace.
... export async function workspaceConfig({ name, defaultScope }: WorkspaceContext) { const configParsed = await getWorkspaceConfigTemplateParsed(); configParsed['teambit.workspace/workspace'].name = name; configParsed['teambit.workspace/workspace'].icon = 'https://my-organization/my-logo.svg'; ... return stringifyWorkspaceConfig(configParsed); }
Set a defaultScope
The default scope can be added when we generate our workspace but if users forget to add the --default-scope <myScope> flag then we can set a default scope for them.
... export async function workspaceConfig({ name, defaultScope }: WorkspaceContext) { const configParsed = await getWorkspaceConfigTemplateParsed(); configParsed['teambit.workspace/workspace'].name = name; ... configParsed['teambit.workspace/workspace'].defaultScope = defaultScope || 'my organization'; ... return stringifyWorkspaceConfig(configParsed); }
It is more than likely that you have already created your own component generator to generate components to you organization's liking that include the correct styling method, docs etc. We can register this component generator aspect so that it will be available for our workspace to use.
... export async function workspaceConfig({ name, defaultScope }: WorkspaceContext) { const configParsed = await getWorkspaceConfigTemplateParsed(); configParsed['teambit.workspace/workspace'].name = name; ... configParsed['teambit.generator/generator'] = { aspects: ['learn-bit-react.base-ui/component-generator'] }; configParsed['learn-bit-react.base-ui/component-generator'] = {}; ... return stringifyWorkspaceConfig(configParsed); }
You may need to add some components as dependencies to your workspace or you may need to add peerDependencies.
... export async function workspaceConfig({ name, defaultScope }: WorkspaceContext) { const configParsed = await getWorkspaceConfigTemplateParsed(); configParsed['teambit.workspace/workspace'].name = name; ... configParsed['teambit.dependencies/dependency-resolver'].policy = { "dependencies": { "@company/scope.namespace.component": "0.0.1", }, "peerDependencies": { "react": "^16.8.0 || ^17.0.2", "react-dom": "^16.8.0 || ^17.0.2" } ... return stringifyWorkspaceConfig(configParsed); }
You can add any config to the workspace.json file using configParse[...].keyName ={}