简体   繁体   English

如何将 Next.js 应用程序发布为 npm 包?

[英]How to publish Next.js app as npm package?

I have a web app built on Next.js.我有一个基于 Next.js 构建的网络应用程序。 I want to publish this app as npm package so it can be used in other projects.我想将此应用程序发布为 npm 包,以便可以在其他项目中使用。 I tried to find resources and help using google but did not find any useful information.我试图使用谷歌查找资源和帮助,但没有找到任何有用的信息。

Is it possible?可能吗? if yes how can I achieve this?如果是的话,我怎么能做到这一点?

Thanks谢谢

I have almost the same need.我几乎有同样的需求。 I created a blog using next js pages and i want to share these pages for 2 next js projects.我使用下一个 js 页面创建了一个博客,我想为 2 个下一个 js 项目共享这些页面。

Until now , i've been able to make it using vite / rollup builder this way (simplified):到现在为止,我已经能够以这种方式使用 vite / rollup 构建器(简化):

NPM package: NPM 包:
// node_modules/@namespace/next-blog/pages/ssr/BlogArticle.tsx
export SSRBlogArticle = getServerSideProps(...) {...}
export BlogArticlePage: NextPage = (SSRProps) => <Blog {..props} />
Using Package in my main next js app在我的主要下一个 js 应用程序中使用 Package
// ./src/pages/blog.tsx
import { SSRBlogArticle, BlogArticlePage } from '@namespace/next-blog'

export getServerSideProps = SSRBlogArticle

const BlogPage: NextPageWithLayout = BlogArticlePage

// some layout
BlogPage.getLayout = (page) => <Layout>{page}</Layout>

export default BlogPage

The problem is about the usage of process.ENV and useRouter .问题在于process.ENVuseRouter的使用。 next/link seems not to work... next/link似乎不起作用...

Here is my vite configuration file :这是我的 vite 配置文件:
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import dts from 'vite-plugin-dts'
import gql from 'vite-plugin-simple-gql'
import tsconfigPaths from 'vite-tsconfig-paths'
import * as path from 'path'
import pkg from './package.json'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    react(),
    tsconfigPaths(),
    gql(),
    dts({
      insertTypesEntry: true,
    }),
  ],
  resolve: {
    alias: [{ find: '@', replacement: path.resolve(__dirname, 'src') }],
  },
  build: {
    lib: {
      entry: path.resolve(__dirname, 'src/index.ts'),
      name: 'NextBlog',
      formats: ['es', 'cjs'],
      fileName: (format) => `index.${format}.js`,
    },
    rollupOptions: {
      external: [
        ...Object.keys(pkg.dependencies),
        ...Object.keys(pkg.peerDependencies),
      ],
    },
  },
})

So i would like to add more questions to the original one :所以我想在原来的问题上添加更多问题:

  • Can we read env file from npm packages?我们可以从 npm 包中读取 env 文件吗? process.ENV reading main app env file ? process.ENV 读取主应用程序 env 文件?
  • Why useRouter is not working properly?为什么 useRouter 不能正常工作?
  • Am i doing it right?我做对了吗? Is it good practice?这是好习惯吗?

Thanks for your help :)谢谢你的帮助 :)

Edit编辑

Process.env进程.env
  • I've managed to find out why all process.env were removed from build, vitejs removes them and replace with {} .我已经设法找出为什么所有process.env都从构建中删除, vitejs将它们删除并替换为{} Solution is :解决方案是:
define: {
  // keep process.env* vars in code bundle
  'process.env': 'process.env',
},
useRouter用户路由器

Still impossible to understand the issue with it...仍然无法理解它的问题......

Here one example error on useRouter in main app when clicking on next/link:这是单击下一步/链接时主应用程序中 useRouter 的一个示例错误:

Uncaught TypeError: Cannot read properties of null (reading 'push')
    at linkClicked (index.es.js?4bcb:3731:1)
    at onClick (index.es.js?4bcb:3830:1)
    at HTMLUnknownElement.callCallback (react-dom.development.js?ac89:4161:1)
    at Object.invokeGuardedCallbackDev (react-dom.development.js?ac89:4210:1)
    at invokeGuardedCallback (react-dom.development.js?ac89:4274:1)
    at invokeGuardedCallbackAndCatchFirstError (react-dom.development.js?ac89:4288:1)
    at executeDispatch (react-dom.development.js?ac89:9038:1)
    at processDispatchQueueItemsInOrder (react-dom.development.js?ac89:9070:1)
    at processDispatchQueue (react-dom.development.js?ac89:9083:1)
    at dispatchEventsForPlugins (react-dom.development.js?ac89:9094:1)
    at eval (react-dom.development.js?ac89:9285:1)
    at batchedUpdates$1 (react-dom.development.js?ac89:26096:1)
    at batchedUpdates (react-dom.development.js?ac89:3988:1)
    at dispatchEventForPluginEventSystem (react-dom.development.js?ac89:9284:1)
    at dispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay (react-dom.development.js?ac89:6462:1)
    at dispatchEvent (react-dom.development.js?ac89:6454:1)
    at dispatchDiscreteEvent (react-dom.development.js?ac89:6427:1)

For now, the only work around i'm thinking off is using native a tags...目前,我正在考虑的唯一解决方法是使用原生 a 标签......

Edit 2编辑 2

I have finally found out the solution : to make router object not null inside of my package, i have to pass it from main nextjs app to page's package.我终于找到了解决方案:要使我的包内的路由器对象不为空,我必须将它从主要的 nextjs 应用程序传递到页面的包。 Inside of the package, i had to wrap my components with RouterContext :在包内部,我必须用RouterContext包装我的组件:

// package next page
import { RouterContext } from 'next/dist/shared/lib/router-context' // next 12

const MyPackagePage = (props) => {
  <RouterContext.Provider value={props.router}>
    <MyComponents ... />
  </RouterContext.Provider>
}

// main next app
const Page = (props) => {
  const router = useRouter()
  return MyPackagePage({ router, ...props })
}

Now works fine.现在工作正常。 Less easy to integrate and more boilerplate code, but at least it's possible de export next pages in npm packages.不太容易集成和更多样板代码,但至少可以在 npm 包中导出下一页。

You can use semantic-release npm package.您可以使用semantic-release npm 包。

In your package.json file you should add follow configuration在您的package.json文件中,您应该添加以下配置

  "release": {
    "branches": [
      "master"
    ],
    "plugins": [
      "@semantic-release/commit-analyzer",
      "@semantic-release/release-notes-generator",
      [
        "@semantic-release/changelog",
        {
          "changelogFile": "CHANGELOG.md"
        }
      ],
      "@semantic-release/npm",
      "@semantic-release/github",
      [
        "@semantic-release/git",
        {
          "assets": [
            "CHANGELOG.md",
            "package.json",
            "package-lock.json"
          ]
        }
      ]
    ]
  }

And your project should be public and should have "private": false in package.json .而且您的项目应该是公开的,并且应该在package.json中有"private": false

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM