nextjs + react + antd 沖突錯誤解決方案


1、使用了 antd-mobile 並且需要對它進行按需加載,下面是官方的文檔,推薦我們使用 babel-plugin-import。

 

2、按照 nextjs 官方文檔我們在 .babelrc 中添加插件

{
  "presets": ["next/babel"],
  "plugins": [
    ["import", { "libraryName": "antd-mobile", "style": true }]
  ]
}

可當我運行的時候報錯了,報錯如下。最開始感到奇怪,我並沒有引入這個包,后來發現其實是 antd-mobile 中有引入它。但是為什么會報錯呢, 便想到應該是 webpack loader 的問題,我認為是 loader 排除了node_modules。(這里解釋一下,node_modules 中的包本應該都是打包好的,但是一些情況下,我們是直接引入源代碼中的模塊的,那這樣的話我們就需要讓我們的 loader 解析 node_modules 中的代碼,然而有些默認配置就是排除了 node_modules 的,這樣就會導致無法解析)。

 

3、后來我終於想清楚了,首先 next-transpile-modules 的目的就是讓 node_modules 中的包可以使用 next-babel-loader ,它的文檔第一句就是這個意思,我當時理解錯誤了。

其次我們再來說說 webpack.externals 這個配置,比如 nextjs 默認就是如下這樣配置的,它把 node_modules 下的 js 作為一個公共的js來處理,當這樣配置以后,webpack 就不會去分析 node_modules 下的 js 的依賴了。

比如我自己在 node_modules 里寫一個文件夾 @test,里面是一個 index.js,index.js require了同級的 b.js,然后我們在 nextjs 的項目代碼里引入 @test/index.js ,編譯時就會報錯,報錯的行就在 require('b.js') 這里。

再來說說 next-transpile-modules, 它做了兩個事情,第一是從 nextjs 默認的 externals 中,排除掉我們定義的  transpileModules: ["antd-mobile"],這樣 antd-mobile 中的 js 就會被 webpack 正常解析依賴了。而后新建了一個 next-babel-loader ,include 的值是 transpileModules 配置的 ["antd-mobile"]。 由於我們的 antd-mobile 中的代碼不需要被 next-babel-loader 解析,甚至如果使用 next-babel-loader 解析就會報錯,因此我前面的配置把它添加的 loader 的 include 給清空了,這樣所有的配置就 ok 了。因此我們只需要它其中的 externals 功能,ok, next.config.js 最終代碼如下(  .babelrc  參照上面不變)

const withLess = require("@zeit/next-less");
const withCss = require("@zeit/next-css");
const withPlugins = require("next-compose-plugins");
const cssLoaderGetLocalIdent = require("css-loader/lib/getLocalIdent.js");
const path = require('path');

module.exports = withPlugins([withLess,withCss], {
  cssModules: true,
  cssLoaderOptions: {
    camelCase: true,
    localIdentName: "[local]___[hash:base64:5]",
    getLocalIdent: (context, localIdentName, localName, options) => {
      let hz = context.resourcePath.replace(context.rootContext, "");
      if (/node_modules/.test(hz)) {
        return localName;
      } else {
        return cssLoaderGetLocalIdent(
          context,
          localIdentName,
          localName,
          options
        );
      }
    }
  },
  webpack(config){
    if(config.externals){
      const includes = [/antd-mobile/];
      config.externals = config.externals.map(external => {
        if (typeof external !== 'function') return external;
        return (ctx, req, cb) => {
          return includes.find(include =>
            req.startsWith('.')
              ? include.test(path.resolve(ctx, req))
              : include.test(req)
          )
            ? cb()
            : external(ctx, req, cb);
        };
      });
    }
    return config;
  }
});

注意:參考子慕大詩人博——完美融合nextjs和antd


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM