一、使用了 antd-mobile 而且須要對它進行按需加載,下面是官方的文檔,推薦咱們使用 babel-plugin-import。css
二、按照 nextjs 官方文檔咱們在 .babelrc 中添加插件html
{ "presets": ["next/babel"], "plugins": [ ["import", { "libraryName": "antd-mobile", "style": true }] ] }
可當我運行的時候報錯了,報錯以下。最開始感到奇怪,我並無引入這個包,後來發現實際上是 antd-mobile 中有引入它。可是爲何會報錯呢, 便想到應該是 webpack loader 的問題,我認爲是 loader 排除了node_modules。(這裏解釋一下,node_modules 中的包本應該都是打包好的,可是一些狀況下,咱們是直接引入源代碼中的模塊的,那這樣的話咱們就須要讓咱們的 loader 解析 node_modules 中的代碼,然而有些默認配置就是排除了 node_modules 的,這樣就會致使沒法解析)。node
三、後來我終於想清楚了,首先 next-transpile-modules 的目的就是讓 node_modules 中的包可使用 next-babel-loader ,它的文檔第一句就是這個意思,我當時理解錯誤了。webpack
其次咱們再來講說 webpack.externals 這個配置,好比 nextjs 默認就是以下這樣配置的,它把 node_modules 下的 js 做爲一個公共的js來處理,當這樣配置之後,webpack 就不會去分析 node_modules 下的 js 的依賴了。web
好比我本身在 node_modules 裏寫一個文件夾 @test,裏面是一個 index.js,index.js require了同級的 b.js,而後咱們在 nextjs 的項目代碼裏引入 @test/index.js ,編譯時就會報錯,報錯的行就在 require('b.js') 這裏。babel
再來講說 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 參照上面不變)antd
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和antdless