【问题标题】:Is there a way to use Materialize CDN with Next.js?有没有办法将 Materialize CDN 与 Next.js 一起使用?
【发布时间】:2021-12-12 13:45:12
【问题描述】:

我正在构建一个 Next.js 应用程序,并希望将 Materialize CDN 与它一起使用。在 React 中,我只需在 public/index.html 文件中添加 CDN 链接就可以了。 Next 似乎没有,我被困在如何做到这一点。

我试过了

npm install materialize-css@next --save

然后我像这样将它导入pages/_app.tsx

import 'materialize-css/dist/css/materialize.min.css';
import 'materialize-css'

当它只是第一次导入时,它运行良好,但是当我导入第二个添加JS时,它会抛出这个错误:

Server Error
ReferenceError: window is not defined

This error happened while generating the page. Any console logs will be displayed in the terminal window.

此外,通过这种导入,我无法对 CSS 进行任何自定义,这就是我想使用 CDN 的原因。我已经好几天没有运气了。

【问题讨论】:

    标签: css reactjs next.js materialize


    【解决方案1】:

    通过 CDN 使用 Materialise

    作为Daniel mentioned in his answer,您可以在自定义_document 中添加CDN 链接,以便CSS 和JavaScript 都能在浏览器中正确加载。

    // /pages/_document.js
    
    class MyDocument extends Document {
        render() {
            return (
                <Html lang="en">
                    <Head>
                        <link
                            rel="stylesheet"
                            href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css"
                        />
                    </Head>
                    <body>
                        <Main />
                        <NextScript />
                        <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
                    </body>
                </Html>
            );
        }
    }
    

    因为 Materialize 在内部使用 Web API,所以您需要在 useEffect 中访问附加到 window 的 Materialize 实例。这可以防止在 Next.js 在服务器上预渲染页面时出现ReferenceError: window is not defined 错误。

    这里有一个小例子,说明如何在渲染轮播的组件中使用 Materialize。

    const MaterializeCarousel = () => {
        useEffect(() => {
            const elems = document.querySelectorAll('.carousel');
            const instances = window.M.Carousel.init(elems);
        }, []);
    
        return (
            <div className="carousel">
                <a className="carousel-item" href="#one!"><img src="https://lorempixel.com/250/250/nature/1" /></a>
                <a className="carousel-item" href="#two!"><img src="https://lorempixel.com/250/250/nature/2" /></a>
                <a className="carousel-item" href="#three!"><img src="https://lorempixel.com/250/250/nature/3" /></a>
                <a className="carousel-item" href="#four!"><img src="https://lorempixel.com/250/250/nature/4" /></a>
                <a className="carousel-item" href="#five!"><img src="https://lorempixel.com/250/250/nature/5" /></a>
            </div>
        );
    };
    

    通过 npm 包使用 Materialise

    另一种选择是通过其 npm 包 materialize-css 使用库。

    您首先需要导入全局 CSS,就像您在 _app 中所做的那样。

    import 'materialize-css/dist/css/materialize.min.css';
    

    无法在此处加载 JavaScript 代码,如前所述,它使用了在服务器上不起作用的 Web API。

    相反,以相同的轮播组件为例,您应该在useEffect 中动态导入materialize-css,以便它只在客户端加载。

    const MaterializeCarousel = () => {
        useEffect(() => {
            const init = async () => {
                const M = await import('materialize-css');
                const elems = document.querySelectorAll('.carousel');
                const instances = M.Carousel.init(elems);
            };
            init();
        }, []);
    
        return (
            <div className="carousel">
                <a className="carousel-item" href="#one!"><img src="https://lorempixel.com/250/250/nature/1" /></a>
                <a className="carousel-item" href="#two!"><img src="https://lorempixel.com/250/250/nature/2" /></a>
                <a className="carousel-item" href="#three!"><img src="https://lorempixel.com/250/250/nature/3" /></a>
                <a className="carousel-item" href="#four!"><img src="https://lorempixel.com/250/250/nature/4" /></a>
                <a className="carousel-item" href="#five!"><img src="https://lorempixel.com/250/250/nature/5" /></a>
            </div>
        );
    };
    

    【讨论】:

      【解决方案2】:

      不要在_app.tsx 中执行此操作,而是在_document.js 文件中执行此操作。这个文件是你在 NextJS 项目中增加 html 和 body 标签的地方。请务必注意,它必须是 .js 文件,而不是 .tsx。

      默认情况下,该文件不存在于您的项目中,它是由 nextJS 自动生成的,但您可以在 pages 文件夹中创建它以覆盖默认文件夹并在那里导入 CDN。

      the official documentation 中有 _document.js 模板和更多信息。

      【讨论】:

        猜你喜欢
        • 2017-09-24
        • 2022-02-17
        • 1970-01-01
        • 2018-03-15
        • 2016-11-01
        • 1970-01-01
        • 2018-09-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多