क्या मैं CSS और JS को अलग-अलग बनाने के लिए वेबपैक का उपयोग कर सकता हूं?


86

मेरे पास है:

  1. जेएस फाइलें जिन्हें मैं बंडल करना चाहता हूं।
  2. कम फ़ाइलें जिन्हें मैं CSS पर संकलित करना चाहता हूं (@imports को एक बंडल में हल करना)।

मैं इन्हें दो अलग-अलग इनपुट के रूप में निर्दिष्ट करने की उम्मीद कर रहा था और दो अलग-अलग आउटपुट (संभवतया एक्सट्रैक्ट-टेक्स्ट-वेबपैक-प्लगइन के माध्यम से)। वेबपैक के पास संकलन करने के लिए सभी उचित प्लगइन्स / लोडर हैं, लेकिन यह अलगाव को पसंद नहीं करता है।

मैंने उन लोगों के उदाहरण देखे हैं, जिन्हें जेएस से सीधे अपनी LESS फ़ाइलों की आवश्यकता होती है, जैसे कि require('./app.less');उन फ़ाइलों को बंडल में शामिल करने के लिए वेबपैक को बताने के अलावा और कोई कारण नहीं है। यह आपको केवल एक प्रविष्टि बिंदु की अनुमति देता है, लेकिन यह वास्तव में मेरे लिए गलत लगता है - मुझे अपने जेएस में लेस की आवश्यकता क्यों होगी जब इसका मेरे जेएस कोड से कोई लेना-देना नहीं है?

मैंने कई प्रविष्टि बिंदुओं का उपयोग करने की कोशिश की, दोनों प्रविष्टि JS और मुख्य LESS फ़ाइल को सौंप दिया, लेकिन कई प्रविष्टि बिंदुओं का उपयोग करते समय, वेबपैक एक बंडल बनाता है जो JS को लोड पर निष्पादित नहीं करता है - यह सभी को बंडल करता है, लेकिन यह नहीं जानता स्टार्टअप पर क्या किया जाना चाहिए।

क्या मैं सिर्फ वेबपैक का गलत इस्तेमाल कर रहा हूं? क्या मुझे इन अलग-अलग मॉड्यूल के लिए वेबपैक के अलग-अलग इंस्टेंस चलाने चाहिए? यदि मुझे अपने जेएस में मिश्रण नहीं करना है तो क्या मुझे गैर-जेएस परिसंपत्तियों के लिए वेबपैक का उपयोग करना चाहिए?


मैं निम्नलिखित ट्यूटोरियल मीडियम
wilo087

जवाबों:


29

यदि मुझे अपने जेएस में मिश्रण नहीं करना है तो क्या मुझे गैर-जेएस परिसंपत्तियों के लिए वेबपैक का उपयोग करना चाहिए?

शायद नहीं। वेबपैक निश्चित रूप से js-centric है, इस निहित धारणा के साथ कि आप जो निर्माण कर रहे हैं वह js अनुप्रयोग है। इसका कार्यान्वयन require()आपको सब कुछ एक मॉड्यूल के रूप में व्यवहार करने की अनुमति देता है (जिसमें सास / LESS के धारावाहिक, JSON, बहुत ज्यादा कुछ भी शामिल है), और स्वचालित रूप से आपके लिए आपका निर्भरता प्रबंधन (वह सब कुछ जो आप requireबंडल कर रहे हैं, और कुछ नहीं)।

जब मुझे अपने JS कोड से कोई लेना-देना नहीं है, तो मुझे अपने JS में LESS की आवश्यकता क्यों होगी?

लोग ऐसा इसलिए करते हैं क्योंकि वे अपने एप्लिकेशन के एक टुकड़े (जैसे एक रिएक्ट घटक, एक बैकबोन व्यू) को js के साथ परिभाषित कर रहे हैं। आवेदन के उस टुकड़े में सीएसएस है जो इसके साथ जाता है। कुछ बाहरी सीएसएस संसाधन के आधार पर जो अलग से बनाया गया है और सीधे जेएस मॉड्यूल से संदर्भित नहीं है, नाजुक है, साथ काम करने के लिए कठिन है, और शैली से बाहर निकल सकता है, आदि। वेबपैक आपको सब कुछ मॉड्यूलर रखने के लिए प्रोत्साहित करता है, इसलिए आपके पास सीएसएस है (Sass, जो कुछ भी) आंशिक रूप से उस js घटक के साथ चला जाता है, और js घटक require()ने निर्भरता को स्पष्ट करने के लिए इसे (आपको और निर्माण उपकरण को, जो कभी भी उन शैलियों का निर्माण नहीं करता है जिनकी आपको आवश्यकता नहीं है)।

मुझे नहीं पता कि क्या आप CSS को बंडल करने के लिए webpack का उपयोग कर सकते हैं (जब CSS फाइलों को किसी js से संदर्भित नहीं किया जाता है)। मुझे यकीन है कि आप प्लगइन्स आदि के साथ कुछ तार कर सकते हैं, लेकिन सुनिश्चित नहीं है कि यह बॉक्स से बाहर संभव है। यदि आप CSS फाइलों का संदर्भ अपने js से करते हैं, तो आप आसानी से CSS टेक्स्ट को एक्स्ट्रेक्ट टेक्स्ट प्लगइन के साथ अलग फ़ाइल में बंडल कर सकते हैं, जैसा कि आप कहते हैं।


18

require('main/less)आपके जेएस में से किसी में भी उपयोग किए बिना एक अलग सीएसएस बंडल उत्पन्न किया जा सकता है , लेकिन जैसा कि ब्रेंडन ने अपने उत्तर के पहले भाग में बताया है कि वेबसीपी को वैश्विक जेएस बंडल के लिए मॉड्यूलर जेएस के साथ जाने के लिए डिज़ाइन नहीं किया गया है, हालांकि कुछ विकल्प हैं ।

पहले main.less के लिए एक अतिरिक्त प्रविष्टि बिंदु जोड़ना है, फिर 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
        })
    ]
};

इस पद्धति के साथ समस्या यह है कि आप एक अवांछित जेएस फ़ाइल के साथ-साथ बंडल भी उत्पन्न कर सकते हैं, इस उदाहरण में: style.jsजो सिर्फ एक खाली वेबपैक मॉड्यूल है।

एक अन्य विकल्प मौजूदा वेबपैक प्रविष्टि बिंदु पर मुख्य कम फ़ाइल जोड़ना है:

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

यह आदर्श है यदि आपके पास केवल 1 प्रवेश बिंदु है, लेकिन यदि आपके पास अधिक है, तो आपका वेबपैक कॉन्फ़िगरेशन थोड़ा अजीब लगेगा, क्योंकि आपको मनमाने ढंग से चुनना होगा कि मुख्य कम फ़ाइल को जोड़ने के लिए कौन सा प्रवेश बिंदु है।


10

BDMason के पूर्व उत्तर को और स्पष्ट करने के लिए - ऐसा लगता है कि प्रत्येक पृष्ठ के लिए JS और CSS बंडल बनाने के लिए वांछनीय कॉन्फ़िगरेशन ऐसा होगा:

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

और फिर [name]स्विच का उपयोग करें:

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

पूर्ण कॉन्फ़िगरेशन - कुछ परिवर्धन से जुड़ा हुआ नहीं है (हम वास्तव में LESS के बजाय SASS का उपयोग कर रहे हैं):

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

9

मिनी-सीएसएस-एक्सट्रैक्ट प्लगइन के साथ वेबपैक 4 समाधान

वेबपैक टीम एक्सट्रेक्ट टेक्स्ट प्लगइन पर मिनी-सीएसएस-एक्सट्रैक्ट का उपयोग करने की सिफारिश करती है

यह समाधान आपको एक अलग हिस्सा बनाने की अनुमति देता है जिसमें केवल आपकी सीएसएस प्रविष्टियाँ होती हैं:

const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

function recursiveIssuer(m) {
  if (m.issuer) {
    return recursiveIssuer(m.issuer);
  } else if (m.name) {
    return m.name;
  } else {
    return false;
  }
}

module.exports = {
  entry: {
    foo: path.resolve(__dirname, 'src/foo'),
    bar: path.resolve(__dirname, 'src/bar'),
  },
  optimization: {
    splitChunks: {
      cacheGroups: {
        fooStyles: {
          name: 'foo',
          test: (m, c, entry = 'foo') =>
            m.constructor.name === 'CssModule' && recursiveIssuer(m) === entry,
          chunks: 'all',
          enforce: true,
        },
        barStyles: {
          name: 'bar',
          test: (m, c, entry = 'bar') =>
            m.constructor.name === 'CssModule' && recursiveIssuer(m) === entry,
          chunks: 'all',
          enforce: true,
        },
      },
    },
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: '[name].css',
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader'],
      },
    ],
  },
};

यहाँ मेरी व्यक्तिगत परियोजनाओं में से एक म्यूटेंटल प्रविष्टियों का उपयोग करके एक अधिक विरोधाभासी उदाहरण दिया गया है:

const ManifestPlugin = require('webpack-manifest-plugin')
const webpack = require('webpack')
const path = require('path')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const VENDOR = path.join(__dirname, 'node_modules')
const LOCAL_JS = path.join(__dirname, 'app/assets/js')
const LOCAL_SCSS = path.join(__dirname, 'app/assets/scss')
const BUILD_DIR = path.join(__dirname, 'public/dist')
const EXTERNAL = path.join(__dirname, 'public/external')

function recursiveIssuer(m) {
  if (m.issuer) {
    return recursiveIssuer(m.issuer);
  } else if (m.name) {
    return m.name;
  } else {
    return false;
  }
}

module.exports = {
  entry: {
    vendor: [
      `${VENDOR}/jquery/dist/jquery.js`,
      `${VENDOR}/codemirror/lib/codemirror.js`,
      `${VENDOR}/codemirror/mode/javascript/javascript.js`,
      `${VENDOR}/codemirror/mode/yaml/yaml.js`,
      `${VENDOR}/zeroclipboard/dist/ZeroClipboard.js`,
    ],
    app: [
      `${LOCAL_JS}/utils.js`,
      `${LOCAL_JS}/editor.js`,
      `${LOCAL_JS}/clipboard.js`,
      `${LOCAL_JS}/fixtures.js`,
      `${LOCAL_JS}/ui.js`,
      `${LOCAL_JS}/data.js`,
      `${LOCAL_JS}/application.js`,
      `${LOCAL_JS}/google.js`
    ],
    'appStyles': [
      `${EXTERNAL}/montserrat.css`,
      `${EXTERNAL}/icons.css`,
      `${VENDOR}/purecss/pure-min.css`,
      `${VENDOR}/purecss/grids-core-min.css`,
      `${VENDOR}/purecss/grids-responsive-min.css`,
      `${VENDOR}/codemirror/lib/codemirror.css`,
      `${VENDOR}/codemirror/theme/monokai.css`,
    ]
  },
  optimization: {
    splitChunks: {
      cacheGroups: {
        appStyles: {
          name: 'appStyles',
          test: (m, c, entry = 'appStyles') =>
            m.constructor.name === 'CssModule' && recursiveIssuer(m) === entry,
          chunks: 'all',
          enforce: true,
        },
      },
    },
  },
  module:  {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: [ 'script-loader'],
      },
      {
        test: /\.(scss|css)$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
        ],
      },
    ],
  },
  mode: 'development',
  resolve: {
    extensions: ['.js', '.css', '.scss']
  },
  output: {
    path: BUILD_DIR,
    filename: "[name].[chunkhash].js",
  },
  plugins: [
    new ManifestPlugin(),
    new MiniCssExtractPlugin({
      filename: '[name].css'
    }),
  ]
};

मुझे लगता है कि यह दृष्टिकोण बहुत मॉड्यूलर नहीं है, लेकिन इससे आपको निर्माण करने के लिए एक नींव मिलनी चाहिए और परियोजनाओं में वेबपैक को अपनाने के लिए एक उत्कृष्ट रणनीति है जहां आप जावास्क्रिप्ट और सीएसएस को मिश्रण नहीं करना चाहते हैं।

इस दृष्टिकोण के लिए नकारात्मक पक्ष यह है कि सीएसएस-लोडर अभी भी एक अतिरिक्त जावास्क्रिप्ट फ़ाइल (चाहे आप इसे उपयोग करने के लिए चुनते हैं या नहीं) उत्पन्न करता है, यह माना जाता है कि वेबपैक 5 में तय किया जाएगा

यदि मुझे अपने जेएस में मिश्रण नहीं करना है तो क्या मुझे गैर-जेएस परिसंपत्तियों के लिए वेबपैक का उपयोग करना चाहिए?

मुझे इसमें कुछ भी गलत नहीं दिखता, लेकिन अंततः यह कई बिल्ड सिस्टम के प्रबंधन के लिए आपकी सहनशीलता पर निर्भर करता है। मेरे लिए यह ओवरकिल जैसा लगता है, इसलिए मेरी प्राथमिकता वेबपैक पारिस्थितिकी तंत्र में बने रहना है।

ऊपर उल्लिखित रणनीतियों के बारे में अधिक जानकारी के लिए, कृपया https://github.com/webpack-contrib/mini-css-extract-plugin#extracting-css-based-on-entry देखें


यह आज डिफ़ॉल्ट उत्तर होना चाहिए
Giona Granata

8

हां, यह संभव है, लेकिन जैसा कि अन्य ने कहा है कि आपको ऐसा करने के लिए अतिरिक्त पैकेजों की आवश्यकता होगी (देखें पैकेज पर निर्भरताएँ)। यहाँ नमूना कोड है जो मैंने अपने बूटस्ट्रैप SCSS -> CSS और बूटस्ट्रैप 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'
                    }
                ]
            }
        ]
    }
};

अतिरिक्त 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"
  }
}

यहाँ ट्यूटोरियल देखें: https://florianbrinkmann.com/en/4240/sass-webpack


1

दूसरों के उल्लेख की तरह आप एक प्लगइन का उपयोग कर सकते हैं।

ExtractTextPlugin पदावनत किया गया है।

आप MiniCssExtractPluginअपने वेबपैक कॉन्फ़िगरेशन में वर्तमान में अनुशंसित का उपयोग कर सकते हैं :

module.exports = {
     entry: {
        home: ['index.js', 'index.less']
     },
     plugins: [
            new MiniCssExtractPlugin({
                filename: '[name].css',
            }),
     ]
}

0

आप अपनी प्रविष्टि JS फाइल में अपनी कम आवश्यकता वाले स्टेटमेंट भी डाल सकते हैं:

in body.js

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

फिर वेबपैक में

  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
})
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.