Nextjs
本篇以nextjs 11
作为案例介绍nextjs的接入方式,其它版本nextjs接入方式会在后续补充,如果你在使用时出现问题,请在github上提issue告知我们。
作为主应用
1、安装依赖
npm i @micro-zoe/micro-app --save
2、初始化micro-app
因为webComponent只能运行在浏览器环境,所以我们在pages/_app.jsx
的useEffect
中进行初始化。
// pages/_app.jsx
import { useEffect } from 'react'
import microApp from '@micro-zoe/micro-app'
function MyApp({ Component, pageProps }) {
useEffect(() => {
// 初始化micro-app
microApp.start()
}, [])
return <Component {...pageProps} />
}
export default MyApp
3、在页面中嵌入子应用
因为micro-app只能运行在浏览器环境,所以在useEffect
中通过变量控制子应用显示。
// pages/my-page.js
import { useState, useEffect } from 'react'
const MyPage = () => {
const [show, changeShow] = useState(false)
useEffect(() => {
changeShow(true)
}, [])
return (
<div>
<h1>子应用</h1>
{
// name:应用名称, url:应用地址
show && (<micro-app name='my-app' url='http://localhost:3000/'></micro-app>)
}
</div>
)
}
export default MyPage
Note
- name:必传参数,必须以字母开头,且不可以带特殊符号(中划线、下划线除外)
- url:必传参数,必须指向子应用的index.html,如:http://localhost:3000/ 或 http://localhost:3000/index.html
作为子应用
1、在主应用中添加ssr配置
当子应用是ssr应用时,主应用需要在micro-app元素上添加ssr属性,此时micro-app会根据ssr模式加载子应用。
<micro-app name='xx' url='xx' ssr></micro-app>
2、设置跨域支持
通过自定义服务设置跨域访问,详情参考 custom-server
步骤1、在根目录创建server.js
server.js
的内容如下:
// server.js
const express = require('express')
const next = require('next')
const config = require('./next.config')
const port = parseInt(process.env.PORT, 10) || 3000
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
app.prepare().then(() => {
const server = express()
// 设置跨域支持
server.all('*', (req, res) => {
res.setHeader('access-control-allow-origin', '*')
return handle(req, res)
})
server.listen(port, (err) => {
if (err) throw err
console.log(`> Ready on http://localhost:${port}/`)
})
})
步骤2、修改package.json
中的scripts
,如下:
"scripts": {
"dev": "node server.js",
"build": "next build",
"start": "cross-env NODE_ENV=production node server.js"
}
3、设置assetPrefix
和 publicRuntimeConfig
在next.config.js
中设置assetPrefix
,为静态资源添加路径前缀,避免子应用的静态资源使用相对地址时加载失败的情况。
// next.config.js
const basePath = '基础路由' // 默认为 '/'
// 静态资源路径前缀
const assetPrefix = process.env.NODE_ENV === 'production' ? `线上域名${basePath}` : `http://localhost:${process.env.PORT || 3000}${basePath}`
module.exports = {
basePath,
assetPrefix,
// 添加 assetPrefix 地址到 publicRuntimeConfig
publicRuntimeConfig: {
assetPrefix,
},
}
assetPrefix
只对js、css等静态资源生效,对本地图片无效。
为此我们将assetPrefix
作为参数传入publicRuntimeConfig
,开发者需要手动通过publicRuntimeConfig
补全图片地址。
方式如下:
import getConfig from 'next/config'
const { publicRuntimeConfig } = getConfig()
const Page = () => {
return (
<div>
<img src={`${publicRuntimeConfig.assetPrefix}/local-img.png`} />
</div>
)
}
export default Page
4、监听卸载
子应用被卸载时会接受到一个名为unmount
的事件,在此可以进行卸载相关操作。
// 监听卸载操作
window.addEventListener('unmount', function () {
// 执行卸载相关操作
})
Note
nextjs默认支持css module功能,如果你使用了此功能,建议关闭样式隔离以提升性能:<micro-app name='xx' url='xx' disableScopecss></micro-app>
5、切换到iframe沙箱
MicroApp有两种沙箱方案:with沙箱
和iframe沙箱
。
默认开启with沙箱,如果with沙箱无法正常运行,可以尝试切换到iframe沙箱。
常见问题
1、使用next/image
组件加载图片失败
解决方式:
在部分nextjs版本中(如:nextjs 11),使用next/image
组件无法正确引入图片,此时推荐使用img元素代替。
2、无法预加载ssr子应用
原因: 因为ssr应用每个路由地址加载的html、js、css等静态资源都不同,所以无法对ssr子应用使用预加载。
3、控制台报错Cannot read properties of null (reading 'tagName')
原因: 当主应用和子应用都是nextjs应用时,next/head
组件冲突。
解决方式: 去掉子应用中next/head
组件。
4、webpack.jsonpFunction冲突,导致加载子应用失败
原因: 当主应用和子应用都是官方脚手架创建的项目,容易造成webpack.jsonpFunction冲突。
解决方式: 修改子应用的webpack配置。
jsonpFunction
是webpack4中的名称,在webpack5中名称为chunkLoadingGlobal
,请根据自己项目的webpack版本设置。
在next.config.js
中配置webpack:
// next.config.js
module.exports = {
webpack: (config) => {
Object.assign(config.output, {
chunkLoadingGlobal: 'webpackJsonp_自定义名称', // webpack5
// jsonpFunction: 'webpackJsonp_自定义名称', // webpack4
globalObject: 'window',
})
return config
},
}
提示
nextjs相关问题可以在nextjs专属讨论贴下反馈。