NextJs 如何按服务端或浏览器端的类型分别打包
source link: https://www.xiabingbao.com/post/react/nextjs-server-client-build-qxpzwi.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
NextJs 是一款优秀的 react 同构直出框架,写一次代码,能够同时在服务端和浏览器端。这是因为 NextJs 会在服务端和浏览器分别打包一份,然后通过数据进行互通。
可是若一些模块只能在浏览器端使用,或只能在服务端使用,该怎么办呢?
1. 只在浏览器端使用的模块
例如@fingerprintjs/fingerprintjs
组件,在 3.0.3 版本及之前,若在 NextJs 中引用时,会直接报错。这是我之前提的 issue:https://github.com/fingerprintjs/fingerprintjs/issues/602。
import FingerprintJS from '@fingerprintjs/fingerprintjs';
useEffect(() => {
FingerprintJS.load();
}, []);
会提示 window 变量不存在的错误:
ReferenceError: window is not defined
这是因为,在 FingerprintJS 模块中,直接调用了 window 变量,而 window 变量只有在浏览器端才有。因此,引用模块后,啥也没干,就已经报错了。
解决方案,就是使用 import 异步引入:
useEffect(() => {
// 这里是浏览器的环境
import('@fingerprintjs/fingerprintjs')
.then((FingerprintJS) => FingerprintJS.load())
.then((fp) => fp.get())
.then((result) => console.log(result.visitorId));
}, []);
这里也仅仅是用 FingerprintJS 模块来举个例子,不过该模块已经从 3.0.6 版本开始解决这个问题了。它会在调用 load 方法时,才会去引用 window 变量。
2. 只在服务端使用的模块
某组件 A 引用了 net 模块、stream 模块等只有在服务端才有的模块,这些模块就只能在服务端使用。
若直接 import 的话,NextJs 也会在浏览器端打包一份,但这个组件在浏览器端又无法使用。
我们公司一个很有名的名字服务-北极星模块,一个只在服务端使用的模块。开发的过程中,是没有感觉的,但打包时就会提示找不到模块:
有两种解决方案。
2.1 只在 server 端引用
NextJs 可以自定义 sever 文件,自定义 server 的文档:https://nextjs.org/docs/advanced-features/custom-server。
如果可以的话,我们把代码逻辑引导 sever 文件中。
// server.js
const { createServer } = require('http');
const { parse } = require('url');
const next = require('next');
const Polaris = require('@tencent/polaris'); // 服务模块在这里引用,就可以了
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
app.prepare().then(() => {
createServer((req, res) => {
// Be sure to pass `true` as the second argument to `url.parse`.
// This tells it to parse the query portion of the URL.
const parsedUrl = parse(req.url, true);
const { pathname, query } = parsedUrl;
if (pathname === '/a') {
console.log(Polaris);
app.render(req, res, '/a', query);
} else if (pathname === '/b') {
app.render(req, res, '/b', query);
} else {
handle(req, res, parsedUrl);
}
}).listen(3000, (err) => {
if (err) throw err;
console.log('> Ready on http://localhost:3000');
});
});
server.js 本身就是服务端的文件,它不会通过 NextJs 的打包系统引入到浏览器端。
2.2 在服务侧按需引入
若不方便将代码执行路径引导到服务端的文件。我们可以在服务侧按需引入,然后在 next.config.js 中配置不要打包到浏览器端。
export default function App {
};
export async function getStaticProps() {
const Polaris = require('@tencent/polaris');
console.log(Polaris);
return {};
}
getStaticProps()
方法在 NextJs 中,就是服务端运行的方法。我们在这里面使用require()
来按需引入。
接着在 next.config.js 中:
const withAntdLess = require('next-plugin-antd-less');
module.exports = (phase) =>
withAntdLess({
webpack: (cfg, { isServer, webpack }) => {
const config = cfg;
if (!isServer) {
// 在浏览器端,忽略这些模块的打包
const ignoreList = ['@tencent\\/polaris', 'dns', 'dotenv'];
ignoreList.forEach((n) => {
config.plugins.push(new webpack.IgnorePlugin({ resourceRegExp: new RegExp(n) }));
});
}
return config;
},
});
在浏览器端,忽略这些模块的打包。
NextJs 是一个在服务端和浏览器都可以运行的 react 框架,我们在使用的使用要特别注意有哪些是只能在客户端使用,哪些是只能在服务端使用。
Recommend
-
9
V2EX › 程序员 两个不同的表,分别查询,然后聚合,如何做分页 kikione ·...
-
6
我们使用前面《SpringCloudAlibaba注册中心与配置中心之利器Nacos实战与源码分析(中)》的两个微服务示例,分别是库存微服务和订单微服务,基于Nacos注册中心和配置中心的使用,前面Nacos我们已基于dock-compose方式部署,我们增加配置数据,这里我们暂时也不...
-
5
一、环境配置centOS 安装 node & 配置全局变量1.centos 安装 node注意:安装和配置过程,使用baseUser用户,而不是root用户安装&...
-
1
Go服务跨平台交叉编译打包与设置版本号 | 小张哥blog 最近在负责维护和开发守护进程、运营平台监控、连接池等相关Go服务,...
-
1
自定义nextJs服务端 - AruSeito自定义nextJs服_ AruSeito 2022/01/21 , 星期五 , 22:57 991 字 4 分钟 6 次本文最后更新于:2022/...
-
4
10天从入门到精通Vue(五)Webpack打包自动打开浏览器、热更新和配置浏览器的默认端口号、打包css、less等 精选 原创
-
5
V2EX › Python Pyinstaller 打包无头浏览器,弹出 cmd 窗口的问题
-
3
实际上除去彩妆和护肤,越来越多其他品类,像宠物类、内衣类的产品都有着巨大的发展潜力。根据艾媒咨询的相关数据显示,宠物类目和内衣的市场规模在不断扩大。(如下图所示)
-
5
V2EX › 程序员 Nextjs 如何访问后端服务的 API 以及如何跨域?
-
2
企业和个人做视频号分别该如何定位? Pai爷运营
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK