Authenticating via the .npmrc
File
To authenticate your project with GitLab's package registry, create or edit the .npmrc
file in the root directory of your project, where your package.json
is located. Add the following lines:
@scope:registry=https://your_domain_name/api/v4/projects/${CI_PROJECT_ID}/packages/npm/
//your_domain_name/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=${CI_JOB_TOKEN}
Explanation:
- Replace
@scope
with the root-level group of the project to which you're publishing the package. - Replace
your_domain_name
with your GitLab domain, e.g.,gitlab.com
. -
${CI_PROJECT_ID}
is the project ID, that you need to be set in the CI runner. -
"${CI_JOB_TOKEN}"
is your job token, that you need to be set in the CI runner.
This configuration ensures that your package manager (e.g., npm or pnpm) authenticates correctly with the GitLab package registry using the CI/CD pipeline.
Publishing a package by using a CI/CD pipeline
To automate the package publishing process, add the following configuration to your .gitlab-ci.yml
file:
image: node:latest # You can replace 'latest' with a specific Node.js version if required
stages:
- deploy
# Publish to package registry
publish-npm:publish-npm:
stage: deploy
before_script:
- echo "Setting up Node environment..."
- curl -fsSL https://fnm.vercel.app/install | bash
- export FNM_PATH="/home/gitlab-runner/.local/share/fnm"
- export PATH="$FNM_PATH:$PATH"
- eval "$(fnm env)"
- fnm install 20
- fnm use 20
- node -v
- npm -v
- npm install -g pnpm
- pnpm install
script:
- echo "@scope:registry=https://your_domain_name/api/v4/projects/${CI_PROJECT_ID}/packages/npm/" > ~/.npmrc
- echo "//your_domain_name/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=${CI_JOB_TOKEN}" >> ~/.npmrc
- pnpm build
- npm publish
rules:
- if: '$CI_COMMIT_BRANCH == "main" && $CI_PIPELINE_SOURCE == "push"' # Run when MR is merged to main branch
Key Points:
- Replace
@scope
with your project’s root-level group. - Replace
your_domain_name
with your domain name, for example, gitlab.com.
Necessary Changes in package.json
To prepare your package.json
for publishing, ensure the following updates are made:
- Remove
private: true
: This flag prevents the package from being published. It should be removed. - Use
vite-plugin-lib-inject-css
: This plugin ensures that CSS is injected into the build file, avoiding the need to import CSS separately after installing the package. - Add
react
andreact-dom
aspeerDependencies
: This ensures that your package doesn’t bundle its own versions ofreact
andreact-dom
, allowing the host project to manage these dependencies.
Here's an example package.json
configuration:
"name": "@scope/package-name",
"files": [
"dist"
],
"sideEffects": [
"**/*.css"
],
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"exports": {
".": {
"import": {
"default": "./dist/index.js"
},
"require": {
"default": "./dist/index.cjs"
}
},
"./css": "./dist/style.css"
},
"publishConfig": {
"registry": "https://your_domain_name/api/v4/projects/${CI_PROJECT_ID}/packages/npm/"
},
"devDependencies": {
"vite-plugin-lib-inject-css": "^2.1.1",
},
"peerDependencies": {
"react": "^18.3.1",
"react-dom": "^18.3.1"
}
Necessary Changes in vite.config.json
Update your vite.config.js
file to include the CSS injection plugin and configure the build process:
import { dirname, join, resolve } from "path";
import { libInjectCss } from "vite-plugin-lib-inject-css";
import { peerDependencies } from "./package.json";
plugins: [libInjectCss()],
build: {
target: "esnext",
minify: false,
lib: {
entry: resolve(__dirname, join("src", "components", "index.js")),
fileName: "index",
formats: ["es", "cjs"],
},
rollupOptions: {
external: ["react/jsx-runtime", ...Object.keys(peerDependencies)],
},
},
Explanation:
- The
libInjectCss
plugin is used to automatically inject CSS into the final build. - The
external
option inrollupOptions
prevents bundling of peer dependencies likereact
andreact-dom
, ensuring they are referenced from the host project instead.
For more references, Publishing a package by using a CI/CD pipeline