If some modules can only be used in the browser side , or only in the server side , how to refer to it in NextJs ?

NextJs is an excellent react isomorphic framework that writes code once and can be used on both the server side and the browser side. This is because NextJs will package a copy on the server side and a copy on the browser side, and then interoperate through the data.

But what should I do if some modules can only be used on the browser side or only on the server side?

1. Browser-only modules

For example, the @fingerprintjs/fingerprintjs component, in version 3.0.3 and earlier, would report an error when referenced in NextJs. This is the issue I mentioned earlier: https://github.com/fingerprintjs/fingerprintjs/issues/602.

For example.

1
2
3
4
5
import FingerprintJS from '@fingerprintjs/fingerprintjs';

useEffect(() => {
  FingerprintJS.load();
}, []);

The error window variable does not exist.

1
ReferenceError: window is not defined

This is because, in the FingerprintJS module, the window variable is called directly, and the window variable is only available on the browser side. Therefore, after referencing the module, nothing is done and an error is already reported.

The solution is to use import to introduce it asynchronously.

1
2
3
4
5
6
7
useEffect(() => {
  // 这里是浏览器的环境
  import('@fingerprintjs/fingerprintjs')
    .then((FingerprintJS) => FingerprintJS.load())
    .then((fp) => fp.get())
    .then((result) => console.log(result.visitorId));
}, []);

This is also just an example with the FingerprintJS module, but it has been fixed since version 3.0.6. It will refer to the window variable only when the load method is called.

2. Serverside only modules

A component A references modules that are only available on the server side, such as the net module, stream module, etc. These modules can only be used on the server side.

If you import directly, NextJs will also package a copy on the browser side, but the component will not be available on the browser side.

Our company has a very famous name service - Polaris module, a module that can only be used on the server side. During the development process, it is not felt, but when packaging it will prompt that the module is not found.

sobyte

There are two solutions.

2.1 Referencing on the server side only

NextJs can customize the sever file and customize the server’s documentation: https://nextjs.org/docs/advanced-features/custom-server.

If possible, we direct the code logic to the sever file.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
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 itself is a server-side file, it is not introduced to the browser side through NextJs’ packaging system.

2.2 On-demand introduction on the server side

If it is not convenient to direct the code execution path to a server-side file. We can introduce it on-demand on the server side and then configure next.config.js not to package it to the browser side.

1
2
3
4
5
6
7
8
9
export default function App {

};

export async function getStaticProps() {
  const Polaris = require('@tencent/polaris');
  console.log(Polaris);
  return {};
}

The getStaticProps() method is, in NextJs, the server-side method to run. We use require() here to introduce it on demand.

Then in next.config.js.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
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;
    },
  });

On the browser side, ignore the packaging of these modules.

3. Summary

NextJs is a server-side and browser can run in the react framework, we use the use of special attention to what is only available on the client side, which is only available on the server side.