web-dev-qa-db-fra.com

Puis-je utiliser webpack pour générer CSS et JS séparément?

J'ai:

  1. JS fichiers que je veux regrouper.
  2. MOINS les fichiers que je veux compiler en CSS (résolution de @imports en un seul paquet).

J'espérais spécifier ces entrées comme deux entrées distinctes et avoir deux sorties distinctes (probablement via extract-text-webpack-plugin). Webpack a tous les plugins/chargeurs appropriés pour faire la compilation, mais il ne semble pas aimer la séparation.

J'ai vu des exemples de personnes ayant besoin de leurs fichiers LESS directement auprès de JS, telles que require('./app.less');, sans autre raison que de demander à Webpack d'inclure ces fichiers dans la liasse. Cela vous permet de n'avoir qu'un seul point d'entrée, mais cela me semble vraiment faux. Pourquoi aurais-je besoin de MOINS dans mon JS alors que cela n'a rien à voir avec mon code JS?

J'ai essayé d'utiliser plusieurs points d'entrée, en transférant à la fois l'entrée JS et le fichier LESS principal, mais lorsque vous utilisez plusieurs points d'entrée, Webpack génère un ensemble qui n'exécute pas l'exécution JS au chargement. ce qui devrait être exécuté au démarrage.

Est-ce que j'utilise mal le WebPack? Dois-je exécuter des instances distinctes de Webpack pour ces modules distincts? Devrais-je même utiliser webpack pour des actifs autres que JS si je ne veux pas les mélanger à mon JS?

38
Brent Traut

Devrais-je même utiliser webpack pour des actifs autres que JS si je ne veux pas les mélanger à mon JS?

Peut être pas. Webpack est définitivement js-centric, avec l'hypothèse implicite que ce que vous construisez est une application js. Son implémentation de require() vous permet de tout traiter comme un module (y compris les partiels Sass/LESS, JSON, à peu près n'importe quoi) et de gérer automatiquement votre dépendance (tout ce que vous require est groupé et rien d’autre).

pourquoi aurais-je besoin de MOINS dans mon JS alors que cela n'a rien à voir avec mon code JS?

Les gens font cela parce qu’ils définissent un élément de leur application (par exemple, un composant React, une vue Backbone) avec js. Ce morceau de l'application a CSS qui va avec. En fonction de certaines ressources CSS externes construites séparément et non directement référencées dans le module js, elles sont fragiles, difficiles à manipuler et peuvent entraîner des styles obsolètes, etc. Webpack vous encourage à conserver tout ce qui est modulaire, afin de disposer d'un code CSS. (Sass, peu importe) partiel qui va avec ce composant js, et le composant js require()s afin de rendre la dépendance claire (pour vous et pour l'outil de construction, qui ne construit jamais de styles dont vous n'avez pas besoin). 

Je ne sais pas si vous pouvez utiliser webpack pour intégrer CSS seul (lorsque les fichiers CSS ne sont référencés à partir d'aucun fichier js). Je suis sûr que vous pouvez connecter quelque chose avec des plugins, etc., mais pas sûr que ce soit possible immédiatement. Si vous référencez les fichiers CSS à partir de votre js, vous pouvez facilement regrouper le fichier CSS dans un fichier séparé avec le plugin Extract Text, comme vous le dites. 

15
Brendan Gannon

Un bundle CSS séparé peut être généré sans utiliser require('main/less) dans l’un de vos JS, mais comme Brendan l’a souligné dans la première partie de sa réponse, Webpack n’est pas conçu pour un bundle CSS global qui côtoie le JS modulaire. options.

La première consiste à ajouter un point d’entrée supplémentaire pour main.less, puis à utiliser le plug-in Extract Text pour créer le bundle CSS:

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
        })
    ]
};

Le problème avec cette méthode est que vous générez également un fichier JS non désiré ainsi que le bundle, dans cet exemple: style.js qui est simplement un module Webpack vide.

Une autre option consiste à ajouter le fichier less principal à un point d’entrée Webpack existant:

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
        })
    ]
};

Ceci est idéal si vous n’avez qu’un seul point d’entrée, mais si vous en avez plus, votre configuration Webpack aura l’air un peu étrange, car vous devrez choisir arbitrairement à quel point d’entrée ajouter le fichier less principal principal.

10
bdmason

Pour clarifier davantage la réponse précédente de bdmason - il semble que la configuration souhaitable serait de créer un ensemble JS et CSS pour chaque page, comme suit:

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

Et utilisez ensuite le commutateur [name]:

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

Configuration complète - avec quelques ajouts non liés à la question (nous utilisons actuellement SASS au lieu de 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

Oui, c'est possible, mais comme d'autres l'ont dit, vous aurez besoin de paquets supplémentaires (voir devDependencies sous package.json). Voici l'exemple de code que j'ai utilisé pour compiler mon bootstrap SCSS -> CSS et Bootstrap JS -> JS.

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'
                    }
                ]
            }
        ]
    }
};

Fichier additional postcss.config.js:

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"
  }
}

Voir le tutoriel ici: https://florianbrinkmann.com/fr/4240/sass-webpack

3
geochanto

Vous pouvez également mettre vos déclarations Less require dans votre fichier JS d’entrée également:

dans body.js

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

Puis dans le 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