How can I combine multiple loaders (CSS, LESS, ttf

2020-07-18 06:28发布

问题:

I'm working on moving a React app to SSR using NextJS and per the docs, I'm using the CSS and LESS modules for Next. The problem is that it seems that only one works at a time.

Some of the app still relies on Bootstrap for now, and I have not been able to get the Bootstrap (either CSS or LESS) to work with these loaders. The main problem is that files like .ttf, .svg, .gif, etc are referenced inside the Bootstrap stylesheets but the loaders aren't in the Next modules.

Here's a general idea of what I'm trying to do with my code:

App.js

import React, {Component} from "react"
import "../node_modules/bootstrap/less/bootstrap.less"
import "../less/landing/foo.less"
import "../less/landing/bar.less"

...

next.config.js (from docs)

const withLess = require('@zeit/next-less')
module.exports = withLess()

Sample error

 error  in ./node_modules/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2

Module parse failed: Unexpected character '' (1:4)
You may need an appropriate loader to handle this file type.
(Source code omitted for this binary file)

 @ ./node_modules/css-loader?{"modules":false,"minimize":false,"sourceMap":true,"importLoaders":1}!./node_modules/bootstrap/dist/css/bootstrap.css 7:4645-4699
 @ ./node_modules/bootstrap/less/bootstrap.less
 @ ./pages/App.js
 @ ./pages/index.js
 @ multi ./pages/index.js

Also, I tried to hack the Webpack config that is used in the module to include those loaders, but I didn't have any luck.

next.config.js

const ExtractTextPlugin = require('extract-text-webpack-plugin')
const cssLoaderConfig = require('@zeit/next-css/css-loader-config')

withLess = (nextConfig = {}) => {
  return Object.assign({}, nextConfig, {
    webpack(config, options) {
      if (!options.defaultLoaders) {
        throw new Error(
          'This plugin is not compatible with Next.js versions below 5.0.0 https://err.sh/next-plugins/upgrade'
        )
      }

      const { dev, isServer } = options
      const { cssModules } = nextConfig
      // Support the user providing their own instance of ExtractTextPlugin.
      // If extractCSSPlugin is not defined we pass the same instance of ExtractTextPlugin to all css related modules
      // So that they compile to the same file in production
      let extractCSSPlugin =
        nextConfig.extractCSSPlugin || options.extractCSSPlugin

      if (!extractCSSPlugin) {
        extractCSSPlugin = new ExtractTextPlugin({
          filename: 'static/style.css'
        })
        config.plugins.push(extractCSSPlugin)
        options.extractCSSPlugin = extractCSSPlugin
      }

      if (!extractCSSPlugin.options.disable) {
        extractCSSPlugin.options.disable = dev
      }

      options.defaultLoaders.less = cssLoaderConfig(config, extractCSSPlugin, {
        cssModules,
        dev,
        isServer,
        loaders: ['less-loader']
      })

      config.module.rules.push({
        test: /\.less$/,
        use: options.defaultLoaders.less
      })

      // ------ start of my custom code --------
      config.module.rules.push({ 
          test: /\.gif$/, 
          use: [{loader: "url-loader?mimetype=image/png" }]
      })

      config.module.rules.push({
          test: /\.woff(2)?(\?v=[0-9].[0-9].[0-9])?$/, 
          use: [{loader: "url-loader?mimetype=application/font-woff"}]
      })

      config.module.rules.push({
          test: /\.(ttf|eot|svg)(\?v=[0-9].[0-9].[0-9])?$/, 
          use: [{loader: "file-loader?name=[name].[ext]"}]
      })
      // ------ end ---------

      if (typeof nextConfig.webpack === 'function') {
        return nextConfig.webpack(config, options)
      }

      return config
    }
  })
}

module.exports = withLess()

TL;DR I need help configuring my Next app to support loading multiple file types at a time

Any help is much appreciated!

回答1:

I was looking for an answer to this as well and found it in the the Next.js documentation where it mentions:

Multiple configurations can be combined together with function composition. For example:

const withTypescript = require('@zeit/next-typescript')`
const withSass = require('@zeit/next-sass')`

module.exports = withTypescript(withSass({
  webpack(config, options) {
    // Further custom configuration here
    return config
  }
}))

`



回答2:

Combined functions are currently not working properly, you need @zeit/next-css@canary and next@canary. And it's not convenient to add configurations separately.

https://github.com/zeit/next-plugins/issues/241


next-compose-plugins may be a better choice:

https://www.npmjs.com/package/next-compose-plugins