はじめに
next.jsでmaterial-uiで使用されているフォントを導入した時に以下のコンパイルエラーでハマったので解法を記録しておきます。
./node_modules/typeface-roboto/index.css 2:0
Module parse failed: Unexpected character '@' (2:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| /* roboto-100normal - latin */
> @font-face {
| font-family: 'Roboto';
| font-style: normal;
結論
このissueの通りに対処すれば動きます。
https://github.com/zeit/next-plugins/issues/432
yarn add @zeit/next-css
yarn add -D url-loader
const withCSS = require("@zeit/next-css");
module.exports = withCSS({
webpack: config => {
config.module.rules.push({
test: /\.(eot|woff|woff2|ttf|svg|png|jpg|gif)$/,
use: {
loader: "url-loader",
options: {
limit: 100000,
name: "[name].[ext]"
}
}
});
return config;
}
});
コンパイルエラー発生までの流れ
nextjs導入
公式のDocに従ってnextjsを導入します。
https://nextjs.org/learn/basics/getting-started/setup
yarn init -y
yarn add react react-dom next
mkdir pages
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start"
},
const Home = () => <h1>Hello World!</h1>;
export default Home;
yarn dev
ここまでは何の問題も無くHelloWorldが表示されるはずです。
material-ui導入
続いてmaterial-uiを導入
公式が入れろと言ってるのでフォントも一緒に入れる
https://material-ui.com/getting-started/installation/
yarn add @material-ui/core typeface-roboto
+ import "typeface-roboto";
ここでyarn dev
を行うと以下のコンパイルエラーが発生します。
./node_modules/typeface-roboto/index.css 2:0
Module parse failed: Unexpected character '@' (2:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| /* roboto-100normal - latin */
> @font-face {
| font-family: 'Roboto';
| font-style: normal;
解決法
結論で貼ったissueの通りに対処すると無事私達のHelloWorldが帰ってきます。
再度掲示します。
yarn add @zeit/next-css
yarn add -D url-loader
const withCSS = require("@zeit/next-css");
module.exports = withCSS({
webpack: config => {
config.module.rules.push({
test: /\.(eot|woff|woff2|ttf|svg|png|jpg|gif)$/,
use: {
loader: "url-loader",
options: {
limit: 100000,
name: "[name].[ext]"
}
}
});
return config;
}
});
なぜ治るのか
これで終わってはissueを貼っただけで味気ないのでなぜこれで治るのかを考えます。
next.config.js
で何をしているのかを考えます。
test
に記載した正規表現にマッチするファイルはパースの際にuse
内に記載したloaderを使う といったconfigを作成しwebpackに設定する、といった事をしています。
今回導入したtypeface-roboto
のindex.css
を見るとわかるように@font-face
を使って拡張子がwoff
, woff2
のファイルを読み込んでいます。
/* roboto-100normal - latin */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-display: swap;
font-weight: 100;
src:
local('Roboto Thin '),
local('Roboto-Thin'),
url('./files/roboto-latin-100.woff2') format('woff2'), /* Super Modern Browsers */
url('./files/roboto-latin-100.woff') format('woff'); /* Modern Browsers */
}
webpackはデフォルトだとこのような特殊な拡張子のファイルは上手くパースできません。
よってこのようにnext.config.js
で明示的に特殊なparser(今回はurl-loader
)を指定してあげることによってパースを成功させることができます。
勿論今回parserが必要なのはwoff
, woff2
だけなので正規表現にこれら2つだけ記載した場合でも動きます。
webpackのloaderについての解説はこの方の記事がわかりやすかったです。
https://qiita.com/takano-h/items/1a6a5a0b9d25a677f7d2