Next.js: CSS-Dateien importieren?

Erstellt am 27. Dez. 2016  ·  102Kommentare  ·  Quelle: vercel/next.js

Manchmal ist es schön, Ihr CSS in eine separate .css -Datei aufzuteilen. Ich habe versucht, Folgendes zu tun:

pages/
└── index
    ├── index.css
    ├── index.js
    └── component.js

Dann habe ich in der index.js versucht:

import css from './index.css'

Und in next.config.js:

module.exports = {
  webpack: function (config) {
    config.module.loaders = (config.module.loaders || []).concat({
      test: /\.css$/, loader: 'raw'
    })
    return config
  }
}

Aber leider gibt es mir immer wieder:

 ERROR  Failed to compile with 1 errors

This dependency was not found in node_modules:

* ./index.css

Scheint, als würde es aus irgendeinem Grund nicht an der richtigen Stelle aufgelöst. Das lokale component.js funktioniert jedoch über import component from './component.js' , daher bin ich mir nicht sicher, was hier los ist.

Hilfreichster Kommentar

Hier ist eine einfache Lösung zum Importieren von CSS-Dateien mit dem Babel-Plugin-Inline-Import :

.babelrc

{
  "presets": ["next/babel"],
  "plugins": [
    [
      "inline-import",
      {
        "extensions": [".css"]
      }
    ]
  ]
}

Seite / Komponente

import "prismjs";

import { PrismCode } from "react-prism";
import prismGlobalStyles from "prismjs/themes/prism.css";

export default () => {
    return (
        <div>
            <style global jsx>
                {prismGlobalStyles}
            </style>
            <PrismCode className="language-javascript">
                {`function(noop) {
                    return noop;
                }`}
            </PrismCode>
            {/* ... */}
        </div>
    );
};

Alle 102 Kommentare

Du meinst, das funktioniert nicht auf dem Server?
Ich denke, wir haben noch keine Problemumgehung dafür. cc @arunoda

Oh, richtig, ich denke, es müsste eine Möglichkeit geben, dass die Webpack-Konfiguration in next.config.js auf beiden Seiten funktioniert, damit dies funktioniert.

Ich habe eine Art Baseball-ähnliches Problem, da ich Next einfach nicht dazu bringen kann, gut mit CSS oder SASS zu spielen. Ich habe ein components -Verzeichnis mit Standard-React-Komponenten, das ich in meine Seiten importiere, aber wenn ich versuche, in SASS- (oder CSS-) Dateien zu importieren, erhalte ich ein ~ "Sie müssen den entsprechenden Loader für diese Datei verwenden". Geben Sie eine Fehlermeldung ein.

Im Allgemeinen importiere ich in React SASS-Dateien und lasse Webpack mit Style-, CSS- und Sass-Loadern kompilieren. Ich habe versucht, diese zur Datei next.config.js hinzuzufügen (und NPM hat sie installiert), erhalte aber immer noch die gleiche Fehlermeldung.

Meine next.config.js Datei:

module.exports = {
  webpack: (config, { dev }) => {
    config.module.rules.push({ test: /\.scss$/, loader: ['style-loader', 'css-loader', 'sass-loader'] });
    return config;
  }
}

Es tut mir leid, wenn diese Fragen dumm klingen oder ich in den Dokumenten etwas Offensichtliches übersehen habe, das die Antworten darauf enthält, aber wenn jemand ein funktionierendes Beispiel für das Importieren / Kompilieren von SASS (oder zumindest CSS) in eine Komponente oder eine Seite mit hat Was auch immer zu den next.config.js hinzugefügt werden muss, um sie zu laden / kompilieren, ich würde es sehr schätzen. Vielen Dank!

Ich benutze CSS-Module-Require-Hook
CSS zum Laufen bringen.

@spacedragon Haben Sie ein Beispiel für die Integration von css-modules-require-hook in Next.js? Ich habe Probleme damit, es zum Laufen zu bringen.

Ich habe immer noch Probleme damit, SASS zum Kompilieren zu bringen, wenn jemand etwas Licht ins Dunkel bringen oder einfach eine CSS-Datei in Next importieren könnte. Dies wäre wünschenswert (über ein Codebeispiel).

Interessant, dass die README-Datei aktualisiert wurde, um das SVG-Loader-Beispiel zu entfernen, und dahingehend geändert wurde, dass das Hinzufügen von Loadern für Dateien wie SVG, CSS und SASS nicht empfohlen wird. Ich bin mir nicht sicher, warum Inline-CSS in Ordnung ist, importiertes CSS jedoch nicht, aber ich bin mir sicher, dass es einen guten Grund dafür gibt. Ich bin mir gerade nicht sicher, welche Strategie am besten geeignet ist, um mit keinem von JS definierten / inline CSS und SASS umzugehen.

@MikeDigitize Siehe Kommentar zu # 627 und # 638.

Es ist tatsächlich möglich und ziemlich einfach, Stile auf der Serverseite zu verarbeiten.

direkt im Knoten:

require.extensions['.css'] = function(file) {
    console.log(file.id)
    return;
}

über babel register:

// from https://babeljs.io/docs/core-packages/babel-register/
require("babel-register")({
  // Optional ignore regex - if any filenames **do** match this regex then they
  // aren't compiled.
  ignore: /regex/,

  // Ignore can also be specified as a function.
  ignore: function(filename) {
    if (filename === '/path/to/es6-file.js') {
      return false;
    } else {
      return true;
    }
  },

  // Optional only regex - if any filenames **don't** match this regex then they
  // aren't compiled
  only: /my_es6_folder/,

  // Setting this will remove the currently hooked extensions of .es6, `.es`, `.jsx`
  // and .js so you'll have to add them back if you want them to be used again.
  extensions: [".es6", ".es", ".jsx", ".js"]
});

über Webpack-Lader:

Ich persönlich verwende den isomorphen Loader, da ich damit kritisches CSS beim Rendern auf dem Server einbinden kann. Hot Reloading und andere DX-bezogene Dinge funktionieren auch. Ich bin kein wirklicher Fan von CSS in JS, da dies die Verwendung von Komponenten von Drittanbietern erschwert und das C irgendwie aus CSS entfernt.

@viktorbezdek Haben Sie Isomorphic-Style-Loader erfolgreich mit next.js verwendet?

@noeljackson Nicht wirklich, aber ich habe vor. Next.js sieht vielversprechend aus und könnte mir viel Zeit sparen, wenn es funktioniert. Werde mich in den nächsten ein oder zwei Wochen darum kümmern und eine Pull-Anfrage einreichen, wenn ich erfolgreich bin.

@viktorbezdek Ich werde ein Kopfgeld auf dieses setzen, da es für ein Projekt, an dem ich arbeite, wirklich entscheidend ist. Ich weiß, dass ich nicht unfähig bin, aber ich verstehe nicht, wie ich die Babel-Transformationen genug debuggen kann, um dies herauszufinden. Ich habe versucht, diese Ideen zu permutieren, und nichts funktioniert zu 100%. Ich konnte Raw-Loader dazu bringen, ein datencodiertes Stylesheet mit Babel-Plugin-Webpack-Loadern einzuziehen, aber keiner der Style-Loader funktioniert. Danke, dass du mitgemacht hast! :) Sehr geschätzt.

Gibt es eine Lösung dafür? Ich würde gerne eine Lösung sehen, damit ich CSS nicht global einbeziehen muss.

FWIW, ich habe gerade meine CSS-Dateien in den Ordner /static . Keine großartige Colocation, aber auch keine große Sache.

Es wird eine Lösung geben. Ich habe es einfach nicht geschafft, es zu beenden. Ich habe vor Ort den ersten Prototyp, der zu funktionieren scheint, aber es dauert einige Stunden, bis er fertig ist. Ich bin mir ziemlich sicher, dass ich nach dem Wochenende fertig bin. Bleib dran.

@matthewmueller Sie verwenden CSS-Module?

@viktorbezdek Danke, dass

Wäre ein solches Babel-Plugin eine Option (auch serverseitig)? https://github.com/gajus/babel-plugin-react-css-modules

Ich habe versucht, dies zum Laufen zu bringen, aber kein Glück: /

Ich habe CSS-Module, die mit babel-plugin-css-modules-transform . Siehe mein hacky Beispiel in meiner Gabel .

Der Nachteil ist, dass Sie den Server beenden und jedes Mal neu starten müssen, wenn Sie Änderungen am CSS vornehmen.

Einige React-Komponenten stellen das Standard-Styling durch eine import -fähige statische Ressource bereit. Zum Importieren des Standardstils von https://github.com/react-component/slider würde man beispielsweise Folgendes verwenden:

import 'rc-slider/assets/index.css';

Es ist sicher möglich, dieses Stylesheet zu kopieren und in das Verzeichnis static/ einzufügen, aber es bleibt bei einem zukünftigen Komponentenupdate nicht mit dem Upstream-Stil synchron und entspricht nicht den Empfehlungen dieser Komponentendokumentation.

Das Problem ist, dass diese CSS-Dateien globale Effekte einführen. Wir müssen in der Lage sein, das CSS zu erfassen und in den React-Lebenszyklus einzufügen, damit es nicht gemountet, vom Server gerendert usw. wird.

Viele Bibliotheken machen das, aber ich denke nicht, dass es ein gutes Muster ist.

Ich bin nicht mit Zeit Next-Interna vertraut, aber könnte eine statische Analyse des import verwendet werden, um das CSS zu registrieren / zu erfassen?

Wir könnten, aber es wäre wirklich seltsam. Ähnlich wie bei etwas, das außerhalb von render() magische Weise in Ihren Komponentenlebenszyklus einfügt.

// Ich dachte, ich würde das für andere teilen

Nun ... Ich habe einfach ein bisschen zu viel Zeit damit verbracht, CSS hier zu hacken, ABER ich bin auf eine Lösung gestoßen, die (für mich) funktioniert. Zugegeben, es ist ein Hack, aber das Hot-Reloading funktioniert ebenso wie das serverseitige Erstellen.

Bei Verwendung von (_shudder_) gulp werden mit dieser gulpfile (https://gist.github.com/auser/25e88e39d83413773c01f4c000ec2806) alle **/*.scss -Dateien zusammen verkettet und in eine Styles -Komponente verschoben, auf die ich mounte die Seite als "normales" Element.

Ich hoffe, dies hilft jemand anderem, bis wir als nächstes echte Post-CSS-Unterstützung erhalten.

Vielen Dank für den Hack @auser , ich habe mir den ganzen Tag die Webpack-Konfiguration ohne Glück angesehen!

Bearbeiten:
Übrigens müssen Sie dem Gulpfile einen Sass-Parser hinzufügen!

Ja und nein ... Ich verwende nur die Erweiterung .scss , um reine CSS-Dateien von vorkompilierten zu unterscheiden. Da postcss (mit precss ) sass gut genug nachahmt, habe ich keine. Fühlen Sie sich frei, mit einem Sass-Parser selbst zu bearbeiten.

Dies scheint derzeit die beste Lösung zu sein. Verwenden Sie gulp, um CSS-Dateien zu kompilieren und inline oder sogar in / static zu erstellen, wenn Sie nichts dagegen haben, kein Hot-Reload durchzuführen.

Ich habe CSS-Import + Hot-Reload auf saubere Weise arbeiten. Das CSS wird als Zeichenfolge importiert und kann vom Benutzer wie jede andere Zeichenfolge auf der Seite eingefügt werden. Bitte schauen Sie sich dieses Beispiel an, helfen Sie mir beim Testen und PRs sind willkommen!

https://github.com/davibe/next.js-css-global-style-test

Ich glaube, dieses Beispiel sollte es in die offiziellen Beispiele von next.j schaffen. Macht es? @rauchg @arunoda @nkzawa (sorry, wenn ich jemanden markiert habe, der nicht direkt involviert ist)

@davibe danke für deine Demo und Babel-Plugin-Wrap-In-Js

Im Beispiel sehe ich die Verwendung einer CSS-Datei und einer SCSS-Datei. Wissen Sie, ob dies mit postcss & cssnext funktionieren würde?

@ khrome83 Ich verstehe nicht warum nicht, ich denke es ist nur eine Frage der Anpassung von .babelrc und next.config.js

@davibe Ich habe festgestellt, dass ich meine App aufgrund Ihrer Konfiguration nicht bereitstellen konnte. Der Build konnte next/babel in der Datei .babelrc nicht lesen. Ich habe ein Problem eingereicht, aber ich hoffe sehr, dass sich daraus eine Lösung ergibt. Ich vermisse die Leichtigkeit von import file.css von create-react-app , aber ich weiß, dass es eine Lösung geben muss :)

Die Lösung, die ich möchte, ist wahrscheinlich in diese Richtung:

https://github.com/zeit/styled-jsx/pull/100#issuecomment -277133969

Wir könnten das Importieren von .css (indem wir es einfach in ein Modul transpilieren, das einen String exportiert) (und ebenso könnten wir .svg indem wir es in eine reine Reaktionskomponente transpilieren).

und ebenso könnten wir .svg unterstützen, indem wir es in eine reine Reaktionskomponente umwandeln

Dies ist ein ziemlich einfacher Trick. Ich werde ein einfaches Beispiel erstellen, das zeigt, wie ich damit in einem anderen Projekt umgegangen bin =)

BEARBEITEN: siehe https://github.com/zeit/next.js/pull/982

Basierend auf dem @ davibe- Beispiel habe ich https://github.com/moxystudio/next.js-style-loader erstellt, das hoffentlich das Hinzufügen von CSS-Dateien zu next.js-Projekten erleichtert. Es ähnelt dem style-loader von Webpack, da es Stylesheets hinzufügt / entfernt, wenn der Benutzer navigiert. Es unterstützt auch SSR.

Es funktioniert gut mit css-loader (mit und ohne CSS-Module), postcss-loader , sass-loader und möglicherweise anderen. Beachten Sie, dass bei Verwendung des CSS-Loaders die Option url auf false gesetzt werden muss. Beucase next.js Bilder, Schriftarten usw. müssen /static . All diese Informationen finden Sie in der README.

Viel Spaß und bitte geben Sie mir Feedback!

Danke für das Repo! Es funktionierte für den Import der CSS-Dateien. Ich versuche Blueprintjs und es scheint, dass die CSS korrekt geladen wird! Die @ font-face-Regel, die das CSS enthält, scheint jedoch nicht zu funktionieren. ::

--------------------bearbeiten----------------------

Es funktioniert tatsächlich, mein schlechtes!
Die Symbole werden jedoch nicht geladen, da das Routing von nextjs standardmäßig nicht zulässt, dass statischer Inhalt außerhalb von / static / bereitgestellt wird und der relative Pfad tatsächlich dazu führt, dass er mit einem Pfad geladen wird, der nicht zulässig ist.

@pencilcheck ja du musst Pfade verwenden, die auf / static zeigen, vielleicht werde ich das in der README klarer machen.

Gibt es eine Problemumgehung bezüglich des relativen Pfads, der in den CSS-Dateien enthalten ist, z. B. Schriftarten atm? Oder muss ich einfach die gesamten Schriftdateien und CSS in einen statischen Ordner kopieren, damit es funktioniert?

@pencilcheck Die CSS-Dateien können außerhalb der statischen /static/file .

Ich verstehe es. Ich verwende jedoch blueprint, ein npm-Paket. Ich möchte in der Lage sein, keine Dateien in node_modules ändern zu müssen.

@pencilcheck Das ist leider nicht möglich. next.js ist sehr streng im Umgang mit Bildern und anderen Assets. Lasst uns diese Konversation nicht verschmutzen und bitte ein Problem im Next-Style-Loader-Repo erstellen, wenn ihr darft.

@tgoldenberg Kannst du das Problem besser beschreiben oder mir sagen, wie ich es reproduzieren soll? Bitte beziehen Sie sich auf mein Repository. Es ist einfacher für mich, Probleme dort zu verfolgen.

@davibe , es war ein Problem mit yarn über npm install . Garn warf einige unerklärliche Fehler, aber als ich es entfernte, funktionierte das Beispiel in der Produktion einwandfrei.

Ich habe gerade 4 Stunden damit verbracht, dies einzurichten, und dachte, es könnte für jeden von Interesse sein, der etwas Zeit sparen möchte. Es wendet Stile beim Ändern automatisch an (genau wie im aktuellen Beispiel), führt das CSS über PostCSS aus und gibt Ihnen lokale Modulnamen ab css-loader . Das Fehlen des letzteren war für mich im gegenwärtigen Zustand der Beispiele „globale CSS“ / „CSS-Importe“ ein großer Deal Breaker.

component.js

import React from 'react';
import stylesheet from './styles.css';

const [css, className] = stylesheet;
const Component = () => (
    <p className={className.paragraph}>
        <Head><style dangerouslySetInnerHTML={{__html: css}} /></Head>
        bazinga
    </p>
);

.babelrc

{
    "presets": [
        "next/babel"
    ],
    "plugins": [
        ["wrap-in-js", {
            "extensions": ["css$"]
        }]
    ]
}

next.config.js
Beachten Sie den erstaunlichen Hack mit exports-loader . Es muss doch einen besseren Weg geben ???

module.exports = {
    webpack: (config) => {
        config.module.rules.push(
            {
                test: /\.css$/,
                use: [
                    {
                        loader: 'emit-file-loader',
                        options: {
                            name: 'dist/[path][name].[ext]'
                        }
                    },
                    {
                        loader: 'raw-loader'
                    },
                    {
                        loader: 'val-loader'
                    },
                    {
                        loader: 'exports-loader',
                        options: {
                            0: 'exports[0][1]',
                            1: 'exports.locals'
                        }
                    },
                    {
                        loader: 'css-loader',
                        options: {
                            modules: true,
                            minimize: true
                        }
                    },
                    {
                        loader: 'postcss-loader'
                    }
                ]
            }
        );

        return config;
    }
};

Ich habe selbst eine Lösung gefunden, die der von @satazor weiter oben im Thread sehr ähnlich ist: https://github.com/jozanza/next-css-json-loader.

Fügen Sie einfach ein paar Zeilen zu Ihrem next.config.js :

module.exports = {
  webpack: config => {
    config.module.rules.push({
      test: /\.css$/,
      loader: 'emit-file-loader',
      options: {
        name: 'dist/[path][name].[ext]',
      }
    }, {
      test: /\.css$/,
      loader: 'babel-loader!next-css-json-loader',
    });
    return config;
  },
};

Stile werden als js-Objekte importiert, sodass die Verwendung mit glamor und ähnlichen Lösungen sehr einfach ist:

// .css files now conveniently expose all styles as js objects
import styles from 'some-package/styles.css';
import { css } from 'glamor';
// ...
<div {...css(styles)}>
  this is a nice box. 
</div>

Prost! 🍻 :)

Gibt es eine Möglichkeit, diese Funktion zum Importieren von Markdown-Dateien als Zeichenfolgen zu verwenden? Ich verwende derzeit Raw-Loader, aber da es sich um ein Webpack-Plugin handelt, funktioniert es auf dem Server nicht.

@kristojorg

Ich habe gerade ein Babel-Plugin für den Markdown-Import geschrieben. Auf meinem Handy gerade, aber wenn Sie meinen GitHub sehen, werden Sie es sehen.

@ khrome83 das klingt

Vielen Dank an khrome83! Ich versuche es mal

Ich musste das sehr schnell machen, deshalb habe ich die Readme-Datei nicht aktualisiert. Aber Sie fügen es einfach als Babel-Plugin hinzu und verwenden es dann

Datei aus 'File.md' importieren;

Ich habe es zum Laufen gebracht, danke !! Sehr hilfreich

Dies ist offtopic, aber da das Problem geschlossen ist, kann ich es gerne näher erläutern :)

Für den Abschlag gibt es zwei Dinge, die Sie tun können.

(1)
Eine besteht darin, die Markdown-Datei als Zeichenfolge einzuschließen und sie dann zur Laufzeit in HTML / React zu übersetzen. Sie können dies mit dem generischen Babel Loader wrap-in-js tun, der es für die Markdown-Dateierweiterung registriert, genau wie es im Beispiel examples/with-globa-stylesheet/.babelrc für next.js für CSS verwendet wird.

(2)
Sie können auch Markdown zur Transpilationszeit mit Markdown-in-js übersetzen
Dies kann in einigen Szenarien interessanter sein, da das Markdown-Dokument bereits vorgerendert ist und daher zur Laufzeit schneller ist (es führt nur js aus). In der Bibliothek können Sie auch benutzerdefinierte React-Komponenten einfügen. Leider müssen Sie in diesem Fall Markdown inline in Ihr source.js wie folgt schreiben.

Wenn Sie (2) auswählen, wissen Sie auch, dass es ein Atom-Plugin gibt, das Syntax-Hilight für die Markdown-in-Js-Syntax bietet und language-markdown-in-js

@davibe danke für den Tipp! Ich würde den Markdown lieber als Build-Zeit analysieren, aber das einzige Problem, das ich mit Markdown-in-js habe, besteht darin, den Backticks beim Komponieren zu entkommen :(. Vielleicht sollte ich versuchen, mit babel als String zu importieren und diesen dann Markdown-in-js zuzuführen ?

@kristojorg

Es gibt ihre Markdown-Renderings. Der Grund, warum ich mein Plugin geschrieben habe, war der gleiche. Ich ziehe Markdown als String, dann führe ich das durch React-Markdown. Dies funktioniert immer besser, da ich Reaktionskomponenten übergeben kann, um Markdown-Rendering-Teile darzustellen, wie z. B. List-Komponente, um alle Listen zu verarbeiten. Funktioniert gut mit Styled JSX.

Gibt es ein Update dazu? Durch die obigen Kommentare sehe ich, dass es derzeit noch keine perfekten Lösungen gibt.
@arunoda
Ist es möglich, ein Beispiel mit isomorphic-style-loader zu haben - https://www.npmjs.com/package/isomorphic-style-loader?

Das wäre perfekt!

Hat jemand eine Lösung für den Import einer Reaktionskomponente aus einem npm-Paket, die wiederum .css- oder .scss-Dateien importiert? Im Grunde genommen werden also Dateien transpiliert, die aus node_modules importiert werden

Ich benutze Create-React-App (CRA) seit einigen Wochen, aber heute bin ich auf Next.js gestoßen und war sehr aufgeregt, weil CRA derzeit kein serverseitiges Rendering (SSR) unterstützt, was wirklich schade ist.
Ich würde gerne sofort zu Next.js wechseln, um SSR-Unterstützung zu erhalten, aber nicht in der Lage zu sein, .scss -Dateien zu importieren, hält mich zurück.
Hat jemand eine Möglichkeit gefunden, der Webpack-Konfiguration einen SASS-Loader hinzuzufügen?

Wenn ich mit cr101 einverstanden bin und keine Unterstützung für CSS / SASS habe, muss ich CSS-Frameworks wie Foundation wegwerfen, was für mich keine Option ist.

Ich habe das von @davibe bereitgestellte Repo bricht mit der Lösung, die er hatte .

Würde mich freuen, wenn jemand eine Lösung dafür gefunden hat. Ein Update auf 2.4.1 war aufgrund des Sicherheitsfehlers unbedingt erforderlich, sodass ich nicht die Möglichkeit habe, wieder herunterzufahren.

@Yuripetusko @ cr101 @tgoldenberg Stimme absolut zu. Ich denke ehrlich, dass das nächste wirklich großartig ist, um sofort arbeiten zu können. Alles ist in Ordnung, auch die fest codierte Struktur (wie das obligatorische Verzeichnis /pages , /static usw.). Aber völlig nicht unterstützte scss Module brechen die ganze Sache für uns. Wir haben eine sehr komplexe scss -Struktur mit automatischen Haltepunkten und einer Neuberechnung des Seitenverhältnisses von allem. Wir haben so hart gearbeitet, um unsere Struktur so perfekt zu machen. Das nächste ist großartig, denn wir können nicht einfach all die scss Sachen rauswerfen, die wir im Moment haben. Nicht unterstützte scss ist die einzige, aber wichtigste Sache, die uns von der Migration zu diesem schönen Tool abhält.

Eigentlich # 1615 - es ist etwas los. @timmywil versucht, isomorphic-style-loader einzurichten, dass es mit next funktioniert. Jeder Interessierte kann mitmachen.

Ich habe jede Lösung ausprobiert, auf die dieser Thread verweist, aber jede davon könnte funktionieren. Also habe ich beschlossen, meinen eigenen Versuch zu machen, und ich habe ihn hier dokumentiert

@ Almeynman danke! Ich werde es auf jeden Fall bei Ihrer Annäherung sehen!
Übrigens habe ich es geschafft, scss Module zum Laufen zu bringen, indem ich diesem Beispiel gefolgt bin. Ich habe nur sass-loader hinzugefügt und Quellkarten aktiviert.

Ich habe es geschafft, next.js CSS (sogar SCSS) auf diese Weise zu unterstützen.

Optimieren Sie zunächst in next.config.js die Webpack-Konfiguration, indem Sie bestimmte Loader und eine DefintPlugin -Instanz hinzufügen.

const webpack = require('webpack');

module.exports = {
  webpack: (config, {dev}) => {
    config.module.rules.push({
      test: /\.scss$/,
      use: [
        'style-loader',
        'css-loader',
        'sass-loader'
      ],
      exclude: /node_modules/,
    });

    config.plugins.push(
      new webpack.DefinePlugin({
        "process.env": {
          // flag to indicate this is for browser-side
          BROWSER: JSON.stringify(true),
       }
      })
    );

    return config;
  }
};

Dann benötigen Sie im Komponentencode eine Stildatei mit Bedingung. Es stellt sicher, dass nur die Browserseitenbündelung über ein Stilmodul verfügt.

if (process.env.BROWSER) {
  require("./style.scss");
}

Wenn Ihnen die if (process.env.BROWSER) nichts ausmachen, funktioniert es perfekt.

Ein guter Ansatz ist hier

@almeynman IMO, das ist kein sehr guter Ansatz, da Sie den CSS-Code für die gesamte Website auf jeder Seite laden, anstatt nur die für diese Seite relevanten CSS-Stile zu laden.
Nur das Importieren der benötigten .scss-Dateien anstelle des CSS für die gesamte Website würde die Größe der Seiten erheblich reduzieren, indem nur der benötigte CSS-Code geladen wird.

@ cr101 Hallo, das wusste ich nicht. Ich habe dieses Setup nicht wirklich verwendet, sondern es nur als Referenz für andere veröffentlicht (ich fand es gut ...). Ich verwende immer noch meinen im Blogbeitrag beschriebenen Ansatz. Wenn Sie mir ein Feedback zu diesem Setup geben könnten, wäre das großartig

Weitere Beispiele und Diskussionen bei Interesse:

https://github.com/iaincollins/nextjs-starter
https://github.com/zeit/next.js/issues/2534
https://github.com/zeit/next.js/tree/v3-beta/examples/with-global-stylesheet

Basierend auf dem oben Gesagten und diesem Thread konnte ich PostCSS verwenden, um Folgendes zu transformieren:

  • Globale SCSS-Datei (Module sind identisch, Sie benötigen lediglich einen Einstiegspunkt, um Ihr gesamtes CSS für die Produktion vorkompilieren zu können).
  • Separates CSS von Drittanbietern mit benutzerdefinierten Schriftarten, auf die über die relative URL verwiesen wird (gelöst durch Inlining Magic).

in eine einzelne CSS-Datei mit /static/styles/app.css für die Produktion, wobei das Hot-Reloading noch funktioniert. Beachten Sie die Verwendung von styled-jsx aber Sie können auch auf <style dangerouslySetInnerHTML={} />

postcss.config.js

module.exports = {
  plugins: [
    require("postcss-easy-import")({ prefix: "_" }), // keep this first
    require("postcss-url")({ url: "inline" })
  ]
};

next.config.js

Loader zum Transformieren von .scss im Dev-Modus zum Hot-Reloading und Extrahieren in eine einzelne .css-Datei in prod. Dies gibt mir build/app.css also habe ich beim Erstellen der Produktion cp build/app.css static/styles/app.css nach next build hinzugefügt, um es für den statischen Export verfügbar zu machen und wie unten gezeigt in einen benutzerdefinierten Header einzubetten.

const ExtractTextPlugin = require('extract-text-webpack-plugin');

export default {
  webpack: (config, { dev }) => ({
    ...config,
    module: {
      ...config.module,
      rules: [
        ...config.module.rules,
        {
          test: /\.(css|scss)/,
          loader: 'emit-file-loader',
          options: {
            name: 'dist/[path][name].[ext]'
          }
        },
        ...(dev
          ? [
              {
                test: /\.css$/,
                use: ['raw-loader', 'postcss-loader']
              },
              {
                test: /\.s(a|c)ss$/,
                use: [
                  'raw-loader',
                  {
                    loader: 'postcss-loader',
                    options: {
                      sourceMap: true
                    }
                  },
                  {
                    loader: 'sass-loader',
                    options: {
                      sourceMap: true
                    }                    
                  }
                ]
              }
            ]
          : [
              {
                test: /\.(css|scss)/,
                use: ExtractTextPlugin.extract({
                  use: [
                    {
                      loader: 'css-loader',
                      options: {
                        importLoaders: 2,
                        modules: false,
                        url: true,
                        minimize: true,
                        localIdentName: '[hash:base64:5]'
                      }
                    },
                    {
                      loader: 'postcss-loader'
                    },
                    {
                      loader: 'sass-loader'
                    }
                  ]
                })
              }
            ]),
        {
          test: /\.(ico|jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2)(\?.*)?$/,
          loader: 'url-loader?limit=100000&&name=[name].[ext]?[hash:8]'
        }
      ]
    },
    plugins: [
      ...config.plugins,
      ...(dev ? [] : [new ExtractTextPlugin('app.css')])
    ]
  }),
};

benutzerdefinierter Header

const inlineCSS =
  process.env.NODE_ENV !== ENV_PRODUCTION && require('styles/index.scss');
...
      <Head>
        {inlineCSS && <style jsx global> {__html: inlineCSS} </style>}
          {process.env.NODE_ENV === ENV_PRODUCTION &&
            <link
              rel="stylesheet"
              type="text/css"
              href={`/static/styles/app.css?${this.props
                .__NEXT_DATA__.buildId}`}
            />}
      </Head>

Hoffe das hilft. Lassen Sie mich wissen, wenn jemand mehr Klarheit benötigt. Ich freue mich auch auf weitere Lösungen. Hoffentlich kann sich irgendwann jemand ein gutes Plugin einfallen lassen, da es immer noch eine ziemlich knifflige und umständliche Integration ist.

Anstatt alle Ihre .scss -Dateien aus einer einzigen CSS-Datei zu extrahieren, ist es viel besser, jede importierte .scss -Datei in eine eigene CSS-Datei zu kompilieren. Auf diese Weise laden Sie nur die CSS-Stile, die Sie auf jeder Seite benötigen.
Ich bin mir nicht sicher, wie du das machen würdest.

Bitte überprüfen Sie meine Pull-Anfrage, ich denke, ich habe eine gute Lösung:
https://github.com/zeit/next.js/pull/2638

@ cr101 das stimmt eigentlich. Wir importieren unsere eigene interne UI-Bibliothek in verschiedene Projekte, daher muss immer ein großer Teil einer Datei geladen werden (nicht ideal, ich weiß, ich arbeite immer noch daran, dieses Biest zu modularisieren). Dies wäre der nächste Schritt von compile and serve 1 file zu X number of files at X locations . Es wird komplizierter, wenn Sie die Kompromisse berücksichtigen, die sich aus der Aufteilung in kleinere CSS-Blöcke im Vergleich zu externen zwischenspeicherbaren UND performanten CDN-gehosteten Versionen ergeben. Ich denke, es wird ein Spaß, aber ein Projekt für sich. BEARBEITEN - definitiv außerhalb des Rahmens für das, was Next verarbeiten soll. Das Beste, was wir anstreben sollten, ist ein Next-Plugin oder -Muster.

Sie sind sich nicht sicher, ob dies zu Leistungsproblemen führt, aber dies ist eine ziemlich einfache Lösung, wenn Sie Styled-Komponenten oder ähnliches verwenden. Erstellen Sie einfach einen CSS-Wrapper:

import styled from 'styled-components';

const Collapse = props => (
  <__Collapse>
    { props.children }
  </__Collapse>
);

export default Collapse;

/**
 * CSS
 */
const __Collapse = styled.div`
  .rc-collapse {
    background-color: #f7f7f7;
    border-radius: 3px;
    border: 1px solid #d9d9d9;
  }
  ...
`;
import RcCollapse from 'rc-collapse';
import Collapse from '~/components/rc/Collapse';

const HelpPage = () => (
  <Collapse>
    <RcCollapse>
      <RcCollapse.Panel header="Title">Content</RcCollapse.Panel>
    </RcCollapse>
  </Collapse>
);

Was mir an diesem Ansatz gefällt, ist, dass ich ihn aus dem Quell-CSS anpassen kann (was ich sowieso meistens tun muss), ohne Überschreibungen über die ursprünglichen Regeln schreiben zu müssen, wenn ich .css importiert habe node_modules .

Hier ist eine einfache Lösung zum Importieren von CSS-Dateien mit dem Babel-Plugin-Inline-Import :

.babelrc

{
  "presets": ["next/babel"],
  "plugins": [
    [
      "inline-import",
      {
        "extensions": [".css"]
      }
    ]
  ]
}

Seite / Komponente

import "prismjs";

import { PrismCode } from "react-prism";
import prismGlobalStyles from "prismjs/themes/prism.css";

export default () => {
    return (
        <div>
            <style global jsx>
                {prismGlobalStyles}
            </style>
            <PrismCode className="language-javascript">
                {`function(noop) {
                    return noop;
                }`}
            </PrismCode>
            {/* ... */}
        </div>
    );
};

@stovmascript Dies ist eine schöne Lösung, aber ich erhalte immer noch Fehler (ich importiere den CSS-Build von https://github.com/Hacker0x01/react-datepicker). Bist du sicher, dass du hier nichts anderes im Spiel hast? Aufgrund der Fehler sieht es so aus, als ob eine andere Ebene des CSS-Ladens erforderlich ist.

@hilarykitz , @stovmascript Lösung funktioniert für mich, können Sie uns den Fehler senden, den Sie erhalten?

@stovmascript - wie werden Sie den Babel-Cache los

  1. Erstellen Sie eine CSS-Datei
  2. Datei importieren
  3. Anwenden
  4. CSS-Datei ändern - neuen Selektor und Stil hinzufügen
  5. Sehen Sie, dass Babel Cache die alte Version behält

@ khrome83 Sie müssen die node_modules / .cache löschen

Ich habe eine bessere Lösung mit dem Babel-Inline-Loader-Plugin gefunden, das den Cache löscht und mit dem oben genannten funktioniert. Das Problem bei dieser Methode ist, dass Sie nur globale Stile anwenden können. Bei Verwendung in einem Nicht- <style jsx global> -Tag wird das Daten-jsx nicht korrekt hinzugefügt, wodurch der Zweck nicht erfüllt wird.

Ich habe eine bessere Lösung mit dem Babel-Inline-Loader-Plugin gefunden, das den Cache löscht und mit dem oben genannten funktioniert. Das Problem bei dieser Methode ist, dass Sie nur globale Stile anwenden können. Bei Verwendung in einem nicht

Ich habe ein Beispiel mit der Lösung von @stovmascript hinzugefügt:

https://github.com/zeit/next.js/pull/3157

Wie schließen Sie mehr als eine externe CSS ein?
Ich verwende 2 Bibliotheken, die es in derselben Komponente erfordern, jede funktioniert separat, aber ich weiß nicht, wie ich sie kombinieren soll.

import rtStyle from 'react-table/react-table.css';
import dpStyle from 'react-datepicker/dist/react-datepicker.css';
...
render() {
    return (
      <div>
        {/* <style jsx global>{ rtStyle }</style> */}
        <style jsx global>{ dpStyle }</style>
...

@ CHarnel versuchen <style jsx global>{ rtStyle }{dpStyle}</style>

@ Almeynman bekommen dies:

Module build failed: SyntaxError: C:/.../components/activeUsersTable.js: 
Expected one child under JSX Style tag, but got 2 (eg: <style jsx>{`hi`}</style>)

@ CHarnel versuchen beide in Template String zu setzen

@ Karl versuchen Sie diesen Ansatz
<style jsx global>{ $ {rtStyle} $ {dpStyle} }</style>

@ Alanhr

Ich versuche, diese CSS in eine JS-Datei zu setzen und sie zu exportieren

import bootstrap from 'bootstrap/dist/css/bootstrap.min.css'
import styles from './index.css'

export default bootstrap + styles

und dann einfach

import styles from '../styles'
...
<style jsx global>{styles}</style>

Mit https://github.com/sheerun/extracted-loader, das ich erstellt habe, können Sie ExtractTextPlugin sowohl für die Entwicklung als auch für die Produktion verwenden.

@comus Ich habe Ihren Ansatz verwendet, funktioniert gut, danke.

@ Sheerun schön, danke

Ich habe next.js ein noch umfassenderes Beispiel vorgelegt:
https://github.com/zeit/next.js/pull/3451

Dies funktionierte früher vor nextjs v4

<style jsx global>{style}</style> <style jsx global>{colors}</style> <style jsx global>{layout}</style>

Was ist der Grund für die Verwendung dieses Ansatzes zum Laden von globalen jsx-Stilen? <style jsx global>{ rtStyle }{dpStyle}</style>

Ich habe mir eine Lösung gemacht, die auf emit-files-loader basiert. Wenn jemand interessiert ist, kann ich es hier posten, aber es basiert auf einem benutzerdefinierten Server-Setup - im Grunde müssen Sie in der Lage sein, ein einzelnes Verzeichnis innerhalb des Build-Verzeichnisses .next statisch zu bedienen. Es könnte wahrscheinlich ohne Server konfiguriert werden, indem auf die Pfadstruktur /_next/... des Servers zurückgegriffen wird.

Ansonsten können Sie import stylesheet from './styles/style.[scss|less|stylus|w/e]'; schreiben und es wird der öffentliche Pfad zu Ihrer Stylesheet-Datei sein, sodass Sie sie in ein <link> . Es enthält ?[hash] für permanentes Caching und führt ein Hot-Reload durch.

Der offizielle Support von https://github.com/zeit/next.js/pull/3578

@ Timneutkens Ich habe dieses gesehen, gibt es eine Schätzung für "sehr bald"? Ich sehe, es ist schon auf Kanarienvogel.
Ich brauchte nur sofort eine Lösung, verbrachte 2-3 Tage damit, nach einer zu suchen, und schaffte es, meine eigene zu schreiben, was im Grunde eine "einfache Lösung" ist. Ich denke sogar darüber nach, es mit extract-text-webpack-plugin zu kombinieren, damit man statisch alle separaten .[css|stylus|less|scss] -Dateien verbinden und sie alle als eine einzige statische Ressource verfügbar machen kann, wie es normalerweise ohne nächste wäre.

Das Hauptproblem hinter diesen Problemen ist meiner Meinung nach, dass im Hintergrund hinter Produktion und Entwickler-Builds viel "Magie" vor sich geht, mit heißem Nachladen und so weiter ... Man könnte wahrscheinlich die Quelle lesen und sehen, wie die Dinge zusammengesetzt sind , aber es wäre großartig, wenn jemand, der es gebaut hat, einige Dokumente dazu schreiben würde. Ich denke, mehr Leute könnten dazu beitragen.

@ Nikolakanacki sehr bald 🙏 🤐

Ich denke sogar darüber nach, es mit dem Extract-Text-Webpack-Plugin zu kombinieren, damit man statisch alle separaten. [css | stylus | less | scss] -Dateien verbinden und sie alle als eine einzige statische Ressource verfügbar machen kann, wie es normalerweise ohne next der Fall wäre .

Die Plugins, die ich für die nächste Version 5 geschrieben habe, tun dies bereits. Sie werden bald Open Source sein 👍

In Bezug auf das Schreiben von Dokumenten auf den Interna planen wir zu dokumentieren, wie alles funktioniert, nachdem v5 veröffentlicht wurde 🙏

@ Timneutkens Danke!

@timneutkens danke für das Update, bitte

Gibt es darüber irgendwelche Neuigkeiten?

Ich bin mir nicht sicher, welche anderen Neuigkeiten Sie erwarten 🤔

Dies wurde in Next.js v5 veröffentlicht.
Es ist sogar in der Readme-Datei https://github.com/zeit/next.js#importing -css - sass - less - stylus-files

Außerdem wurde die erwähnte PR zusammengeführt und dieses Problem ist geschlossen.

Erstellen Sie einfach den Ordner / static im Stammprojekt und legen Sie dann Ihre Datei.css in / static ab zu Header HTML-Struktur Hock.

import Head from 'next/head';
<Head>
          <meta charset="utf-8" />
          <link rel="stylesheet" href="/static/css/custom.css" />
</Head>

und dann überall className verwenden!

@comus

Sehr umfassend und klug. Vielen Dank dafür. Ich habe den ganzen Tag nach dieser Art von Lösung gesucht.

Erstellen Sie einfach den Ordner / static im Root-Projekt und legen Sie Ihre Datei.css in / static ab, dann in den Header-HTML-Struktur-Hock.

import Head from 'next/head';
<Head>
          <meta charset="utf-8" />
          <link rel="stylesheet" href="/static/css/custom.css" />
</Head>

und dann überall className verwenden!

Erstellen Sie einen 'öffentlichen' Ordner im Stammverzeichnis Ihrer Anwendung (in dem sich die Datei package.json befindet).

Support wird über # 8626 hinzugefügt!

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

jesselee34 picture jesselee34  ·  3Kommentare

knipferrc picture knipferrc  ·  3Kommentare

pie6k picture pie6k  ·  3Kommentare

timneutkens picture timneutkens  ·  3Kommentare

sospedra picture sospedra  ·  3Kommentare