Root package.json with workspace directories
{
"name": "events-helsinki-monorepo",
// Set the directories where your apps, packages will be placed
"workspaces": ["apps/*", "packages/*"],
//...
}
The package manager will scan those directories and look for children package.json
. Their
content is used to define the workspace topology (apps, libs, dependencies...).
Create a folder in ./packages/ directory with the name of your package.
Create the package folder
mkdir packages/magnificent-poney
mkdir packages/magnificent-poney/src
cd packages/magnificent-poney
Initialize a package.json with the name of your package.
Rather than typing
yarn init
, prefer to take the ./packages/components/package.json as a working example and edit its values.
Example of package.json
{
"name": "events-helsinki-magnificent-poney",
"version": "0.0.0",
"private": true,
"scripts": {
"clean": "rimraf --no-glob ./tsconfig.tsbuildinfo",
"lint": "eslint . --ext .ts,.tsx,.js,.jsx",
"typecheck": "tsc --project ./tsconfig.json --noEmit",
"test": "run-s 'test:*'",
"test:unit": "echo \"No tests yet\"",
"fix:staged-files": "lint-staged --allow-empty",
"fix:all-files": "eslint . --ext .ts,.tsx,.js,.jsx --fix",
},
"devDependencies": {
"@events-helsinki/eslint-config-bases": "workspace:^",
},
}
First add the package to the app package.json. The recommended way is to use the workspace protocol supported by yarn and pnpm.
cd apps/my-app
yarn add events-helsinki-magnificent-poney@'workspace:^'
Inspiration can be found in apps/nextjs-app/package.json.
package.json
{
"name": "my-app",
"dependencies": {
"events-helsinki-magnificient-poney": "workspace:^",
},
}
Then add a typescript path alias in the app tsconfig.json. This will allow you to import it directly (no build needed)
Inspiration can be found in apps/nextjs-app/tsconfig.json.
Example of tsonfig.json
{
"compilerOptions": {
"baseUrl": "./src",
"paths": {
// regular app aliases
"@/components/*": ["./components/*"],
// packages aliases, relative to app_directory/baseUrl
"events-helsinki-magnificent-poney/*": [
"../../../packages/magnificent-poney/src/*",
],
"events-helsinki-magnificent-poney": [
"../../../packages/magnificent-poney/src/index",
],
},
},
}
PS:
- Don't try to set aliases in the global tsonfig.base.json to keep strict with graph dependencies.
- The star in
events-helsinki-magnificent-poney/*
allows you to import subfolders. If you use a barrel file (index.ts), the alias with star can be removed.
Edit your next.config.js
and enable the experimental.externalDir option.
Feedbacks here.
const nextConfig = {
experimental: {
externalDir: true,
},
};
export default nextConfig;
Using a NextJs version prior to 10.2.0 ?
If you're using an older NextJs version and don't have the experimental flag, you can simply override your webpack config.
const nextConfig = {
webpack: (config, { defaultLoaders }) => {
// Will allow transpilation of shared packages through tsonfig paths
// @link https://github.com/vercel/next.js/pull/13542
const resolvedBaseUrl = path.resolve(config.context, "../../");
config.module.rules = [
...config.module.rules,
{
test: /\.(tsx|ts|js|jsx|json)$/,
include: [resolvedBaseUrl],
use: defaultLoaders.babel,
exclude: (excludePath) => {
return /node_modules/.test(excludePath);
},
},
];
return config;
},
};
PS: If your shared package make use of scss bundler... A custom webpack configuration will be necessary or use next-transpile-modules, see FAQ below.
The packages are now linked to your app, just import them like regular packages: import { poney } from 'events-helsinki-magnificent-poney'
.