wake-up-neo.net

Kann ich mit Webpack CSS und JS separat generieren?

Ich habe:

  1. JS-Dateien, die ich bündeln möchte.
  2. Weniger Dateien, die ich in CSS kompilieren möchte (@imports in ein einzelnes Bundle auflösen).

Ich hatte gehofft, diese als zwei separate Eingaben zu spezifizieren und zwei getrennte Ausgänge zu haben (wahrscheinlich über das extrahierte Text-Webpack-Plugin). Webpack verfügt über alle geeigneten Plugins/Loader, die zum Kompilieren verwendet werden können, aber es scheint die Trennung nicht zu mögen.

Ich habe Beispiele von Leuten gesehen, die ihre LESS-Dateien direkt von JS benötigen, wie z. B. require('./app.less');, aus keinem anderen Grund, als dem webpack mitzuteilen, diese Dateien in das Bundle aufzunehmen. Dies ermöglicht Ihnen, nur einen einzigen Einstiegspunkt zu haben, aber es scheint mir wirklich falsch - warum sollte ich in meiner JS weniger benötigen, wenn es nichts mit meinem JS-Code zu tun hat?

Ich habe versucht, mehrere Einstiegspunkte zu verwenden und dabei sowohl den Eintrag JS als auch die LESS-Hauptdatei einzureichen. Wenn Sie jedoch mehrere Einstiegspunkte verwenden, generiert webpack ein Bündel, das den JS beim Laden nicht ausführt Was soll beim Start ausgeführt werden.

Benutze ich nur das Webpack falsch? Sollte ich separate Webpack-Instanzen für diese separaten Module ausführen? Sollte ich das Webpack auch für Nicht-JS-Assets verwenden, wenn ich sie nicht in meine JS mischen möchte?

38
Brent Traut

Sollte ich das Webpack auch für Nicht-JS-Assets verwenden, wenn ich sie nicht in meine JS mischen möchte?

Vielleicht nicht. Webpack ist definitiv js-centric, mit der implizierten Annahme, dass das, was Sie erstellen, eine js-Anwendung ist. Durch die Implementierung von require() können Sie alles als Modul behandeln (einschließlich Sass/LESS-Partials, JSON und so ziemlich alles) und führt automatisch das Abhängigkeitsmanagement für Sie durch (alles, was Sie require gebündelt haben, und nichts anderes).

warum sollte ich WENIGER in meinem JS benötigen, wenn es nichts mit meinem JS-Code zu tun hat?

Leute tun dies, weil sie einen Teil ihrer Anwendung (z. B. eine React-Komponente, eine Backbone-Ansicht) mit js definieren. Dieser Teil der Anwendung hat CSS, die dazugehört. Abhängig von einer externen CSS-Ressource, die separat erstellt und nicht direkt vom js-Modul referenziert wird, ist sie sehr anfällig, schwieriger zu arbeiten und kann dazu führen, dass Stile nicht mehr aktuell sind usw. Webpack fordert Sie dazu auf, alles modular zu halten (Sass, was auch immer) partielle, die zu dieser js-Komponente gehört, und die js-Komponente require()s, um die Abhängigkeit deutlich zu machen (für Sie und für das Build-Tool, das niemals Stile erstellt, die Sie nicht benötigen). 

Ich weiß nicht, ob Sie Webpack verwenden könnten, um CSS alleine zu bündeln (wenn die CSS-Dateien nicht von js referenziert werden). Ich bin mir sicher, dass Sie etwas mit Plugins usw. verdrahten könnten, aber nicht sicher, ob es möglich ist. Wenn Sie von Ihrem js aus auf die CSS-Dateien verweisen, können Sie das CSS mit dem Plugin "Text extrahieren" auf einfache Weise in einer separaten Datei bündeln. 

15
Brendan Gannon

Ein separates CSS-Paket kann ohne die Verwendung von require('main/less) in einer Ihrer JS generiert werden. Wie Brendan im ersten Teil seiner Antwort jedoch darauf hinweist, ist Webpack nicht für ein globales CSS-Paket für modulare JS ausgelegt, es gibt jedoch einige Optionen.

Der erste besteht darin, einen zusätzlichen Einstiegspunkt für main.less hinzuzufügen und dann das Plugin "Text extrahieren" zum Erstellen des CSS-Pakets zu verwenden:

var webpack = require('webpack'),
    ExtractTextPlugin = require("extract-text-webpack-plugin");

module.exports = {
    entry: {
        home: [
            'js/common',
            'js/homepage'
        ],
        style: [
            'styles/main.less'
        ]
    },
    output: {
        path: 'dist',
        filename: "[name].min.js"
    },
    resolve: {
        extensions: ["", ".js"]
    },
    module: {
        loaders: [{
            test: /\.less$/,
            loader: ExtractTextPlugin.extract("style", "css", "less")
        }]
    },
    plugins: [
        new ExtractTextPlugin("[name].min.css", {
            allChunks: true
        })
    ]
};

Das Problem bei dieser Methode ist, dass Sie auch eine unerwünschte JS-Datei sowie das Bundle generieren. In diesem Beispiel ist style.js ein leeres Webpack-Modul.

Eine weitere Option ist das Hinzufügen der Hauptdatei less zu einem vorhandenen Webpack-Einstiegspunkt:

var webpack = require('webpack'),
    ExtractTextPlugin = require("extract-text-webpack-plugin");

module.exports = {
    entry: {
        home: [
            'js/common',
            'js/homepage',
            'styles/main.less'
        ],
    },
    output: {
        path: 'dist',
        filename: "[name].min.js"
    },
    resolve: {
        extensions: ["", ".js"]
    },
    module: {
        loaders: [{
            test: /\.less$/,
            loader: ExtractTextPlugin.extract("style", "css", "less")
        }]
    },
    plugins: [
        new ExtractTextPlugin("[name].min.css", {
            allChunks: true
        })
    ]
};

Dies ist ideal, wenn Sie nur einen Einstiegspunkt haben, aber wenn Sie mehr haben, wird Ihre Webpack-Konfiguration etwas seltsam aussehen, da Sie willkürlich auswählen müssen, zu welchem ​​Einstiegspunkt die Hauptdatei mit weniger Dateien hinzugefügt werden soll.

10
bdmason

Um die frühere Antwort von bdmason weiter zu verdeutlichen, scheint es wünschenswert, ein JS- und CSS-Paket für jede Seite zu erstellen.

 entry: {
        Home: ["./path/to/home.js", "./path/to/home.less"],
        About: ["./path/to/about.js", "./path/to/about.less"]
    }

Und dann den [name]-Schalter verwenden:

output: {
        path: "path/to/generated/bundles",
        filename: "[name].js"
    },
plugins: new ExtractTextPlugin("[name].css")

Vollständige Konfiguration - mit einigen Ergänzungen, die nicht mit der Frage zusammenhängen (wir verwenden eigentlich SASS anstelle von LESS):

var ExtractTextPlugin = require("extract-text-webpack-plugin");
var debug = process.env.NODE_ENV !== "production";
var webpack = require('webpack');
require('babel-polyfill');

module.exports = [{
    devtool: debug ? "inline-sourcemap" : null,
    entry: {
        Home: ['babel-polyfill', "./home.js","path/to/HomeRootStyle.scss"],
        SearchResults: ['babel-polyfill', "./searchResults.js","path/to/SearchResultsRootStyle.scss"]
    },
    module: {
        loaders: [
            {
                test: /\.jsx?$/,
                exclude: /(node_modules|bower_components)/,
                loader: 'babel-loader',
                query: {
                    presets: ['react', 'es2015'],
                    plugins: ['react-html-attrs', 'transform-class-properties', 'transform-decorators-legacy']
                }
            },
            {
                test: /\.scss$/,
                loader: ExtractTextPlugin.extract("style-loader","css-raw-loader!sass-loader")
            }
        ]
    },
    output: {
        path: "./res/generated",
        filename: "[name].js"
    },
    plugins: debug ? [new ExtractTextPlugin("[name].css")] : [
        new ExtractTextPlugin("[name].css"),
        new webpack.DefinePlugin({
            'process.env':{
                'NODE_ENV': JSON.stringify('production')
            }
        }),
        new webpack.optimize.UglifyJsPlugin({
            compress:{
                warnings: true
            }
        })
    ]
}
];
4
Gilad Barner

Ja, das ist möglich, aber wie andere sagten, werden Sie zusätzliche Pakete dafür benötigen (siehe devDependencies unter package.json). Hier ist der Beispielcode, den ich zum Kompilieren meines Bootstraps SCSS -> CSS und Bootstrap JS -> JS verwendet habe.

webpack.config.js:

module.exports = {
    mode: process.env.NODE_ENV === 'production' ? 'production' : 'development',
    entry: ['./src/app.js', './src/scss/app.scss'],
    output: {
    path: path.resolve(__dirname, 'lib/modules/theme/public'),
    filename: 'js/bootstrap.js'
    },
    module: {
        rules: [
            {
                test: /\.scss$/,
                use: [
                    {
                        loader: 'file-loader',
                        options: {
                            name: 'css/bootstrap.css',
                        }
                    },
                    {
                        loader: 'extract-loader'
                    },
                    {
                        loader: 'css-loader?-url'
                    },
                    {
                        loader: 'postcss-loader'
                    },
                    {
                        loader: 'sass-loader'
                    }
                ]
            }
        ]
    }
};

zusätzliche postcss.config.js-Datei:

module.exports = {
    plugins: {
        'autoprefixer': {}
    }
}

package.json:

{
  "main": "app.js",
  "scripts": {
    "build": "webpack",
    "start": "node app.js"
  },
  "author": "P'unk Avenue",
  "license": "MIT",
  "dependencies": {
    "bootstrap": "^4.1.3",
  },
  "devDependencies": {
    "autoprefixer": "^9.3.1",
    "css-loader": "^1.0.1",
    "exports-loader": "^0.7.0",
    "extract-loader": "^3.1.0",
    "file-loader": "^2.0.0",
    "node-sass": "^4.10.0",
    "popper.js": "^1.14.6",
    "postcss-cli": "^6.0.1",
    "postcss-loader": "^3.0.0",
    "sass-loader": "^7.1.0",
    "style-loader": "^0.23.1",
    "webpack": "^4.26.1",
    "webpack-cli": "^3.1.2"
  }
}

Sehen Sie sich das Tutorial hier an: https://florianbrinkmann.com/de/4240/sass-webpack

3
geochanto

Sie können Ihre Less-Required-Anweisungen auch in Ihre Entry-JS-Datei einfügen:

in body.js

// CSS
require('css/_variable.scss')
require('css/_npm.scss')
require('css/_library.scss')
require('css/_lib.scss')

Dann im Webpack

  entry: {
    body: [
      Path.join(__dirname, '/source/assets/javascripts/_body.js')
    ]
  },

const extractSass = new ExtractTextPlugin({
  filename: 'assets/stylesheets/all.bundle.css',
  disable: process.env.NODE_ENV === 'development',
  allChunks: true
})
0
Ian Warner