CSS ve JS'yi ayrı ayrı oluşturmak için web paketini kullanabilir miyim?


86

Sahibim:

  1. Paketlemek istediğim JS dosyaları.
  2. CSS'ye derlemek istediğim DAHA AZ dosya (@imports'u tek bir pakette çözümleme).

Bunları iki ayrı girdi olarak belirtmeyi ve iki ayrı çıktıya sahip olmayı umuyordum (muhtemelen extract-text-webpack-eklentisi aracılığıyla). Webpack, derleme yapmak için tüm uygun eklentilere / yükleyicilere sahiptir, ancak ayrımı sevmiyor gibi görünüyor.

require('./app.less');Webpack'e bu dosyaları pakete dahil etmesini söylemekten başka hiçbir neden olmadan LESS dosyalarına doğrudan JS'den ihtiyaç duyan insanlara örnekler gördüm . Bu, yalnızca tek bir giriş noktasına sahip olmanıza izin verir, ancak bana gerçekten yanlış geliyor - JS kodumla hiçbir ilgisi yokken neden JS'mde LESS'e ihtiyaç duyayım?

Birden çok giriş noktası kullanmayı denedim, hem giriş JS'yi hem de ana LESS dosyasını içeri aktarmaya çalıştım, ancak birden çok giriş noktası kullanırken, webpack, JS'yi yüklerken çalıştırmayan bir paket oluşturuyor - hepsini topluyor, ancak bilmiyor başlangıçta ne yapılmalı.

Webpack'i yanlış mı kullanıyorum? Bu ayrı modüller için ayrı web paketi örnekleri çalıştırmalı mıyım? JS'mle karıştırmayacaksam, JS olmayan varlıklar için web paketi kullanmalı mıyım?


Aşağıdaki eğitim ortamını
wilo087

Yanıtlar:


29

JS'mle karıştırmayacaksam, JS olmayan varlıklar için web paketi kullanmalı mıyım?

Belki değil. Webpack, oluşturduğunuz şeyin bir js uygulaması olduğu üstü kapalı varsayımıyla kesinlikle js merkezlidir. Uygulaması, require()her şeyi bir modül olarak (Sass / LESS parçaları, JSON, hemen hemen her şey dahil) ele almanıza olanak tanır ve bağımlılık yönetiminizi sizin için otomatik olarak yapar ( requirepaketlediğiniz her şey ve başka hiçbir şey).

JS kodumla hiçbir ilgisi olmadığında neden JS'mde DAHA AZ gerekli olsun?

İnsanlar bunu js ile uygulamalarının bir parçasını (örneğin bir React bileşeni, bir Omurga Görünümü) tanımladıkları için yaparlar. Uygulamanın bu parçası, onunla birlikte gelen CSS'ye sahiptir. Ayrı ayrı oluşturulan ve doğrudan js modülünden referans alınmayan bazı harici CSS kaynaklarına bağlı olarak kırılgandır, üzerinde çalışmak daha zordur ve stillerin güncelliğini yitirmesine neden olabilir. Webpack, her şeyi modüler tutmanızı teşvik eder, böylece bir CSS'ye sahip olursunuz (Sass, ne olursa olsun) bu js bileşeniyle giden kısmi ve js bileşeni require(), bağımlılığı netleştirmek için (size ve ihtiyacınız olmayan stilleri asla oluşturmayan oluşturma aracına).

CSS dosyalarını kendi başına paketlemek için webpack'i kullanabilir miydiniz bilmiyorum (CSS dosyalarına herhangi bir js'den referans verilmediğinde). Eminim eklentiler vb. İle bir şeyler bağlayabilirsiniz, ancak kutunun dışında bunun mümkün olduğundan emin değilim. CSS dosyalarına js'nizden referans verirseniz, söylediğiniz gibi CSS'yi Metin Çıkarma eklentisiyle ayrı bir dosyaya kolayca paketleyebilirsiniz.


18

require('main/less)JS'nizin hiçbirinde kullanılmadan ayrı bir CSS paketi oluşturulabilir , ancak Brendan'ın cevabının ilk bölümünde belirttiği gibi Webpack, küresel bir CSS paketinin modüler JS ile birlikte gidebilmesi için tasarlanmamıştır, ancak birkaç seçenek vardır. .

Birincisi, main.less için fazladan bir giriş noktası eklemek, ardından CSS paketini oluşturmak için Metin Çıkarma eklentisini kullanmaktır:

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

Bu yöntemle ilgili sorun, bu örnekte istenmeyen bir JS dosyası ve paket oluşturmanızdır: style.jsbu sadece boş bir Web paketi modülüdür.

Başka bir seçenek de ana daha az dosyayı mevcut bir Web paketi giriş noktasına eklemektir:

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

Bu, yalnızca 1 giriş noktanız varsa idealdir, ancak daha fazlasına sahipseniz, daha az ana dosyayı ekleyeceğiniz giriş noktasını keyfi olarak seçmeniz gerekeceğinden Webpack yapılandırmanız biraz tuhaf görünecektir.


10

Bdmason'un önceki cevabını daha da açıklığa kavuşturmak için - istenen konfigürasyon her sayfa için bir JS ve CSS paketi oluşturmak gibi görünüyor, örneğin:

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

Ve sonra [name]anahtarı kullanın :

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

Tam konfigürasyon - soruya bağlı olmayan bazı eklemelerle (aslında LESS yerine SASS kullanıyoruz):

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

mini-css-extract eklentili webpack 4 çözümü

web paketi ekibi, metin ayıklama eklentisi yerine mini css-extract kullanılmasını önerir

bu çözüm, yalnızca css girişlerinizi içeren ayrı bir yığın oluşturmanıza olanak tanır:

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

İşte kişisel projelerimden birinden birden fazla girişi kullanan daha uydurma bir örnek:

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

Bu yaklaşımın çok modüler olmadığının farkındayım, ancak size bir temel oluşturmalı ve javascript ve css'yi karıştırmak istemediğiniz projelerde webpack'i benimsemek için mükemmel bir strateji.

Bu yaklaşımın dezavantajı, css-loader'ın hala ek bir javascript dosyası oluşturmasıdır (kullanmayı seçseniz de kullanmasanız da), bu sözde webpack 5'te düzeltilecektir .

JS'mle karıştırmayacaksam, JS olmayan varlıklar için web paketi kullanmalı mıyım?

Bunda yanlış bir şey görmüyorum, ancak sonuçta bu, birden fazla yapı sistemini yönetme konusundaki toleransınıza bağlı. Bana göre bu abartılı gibi geliyor, bu yüzden tercihim web paketi ekosisteminde kalmak.

Yukarıda özetlenen stratejiler hakkında daha fazla bilgi için lütfen https://github.com/webpack-contrib/mini-css-extract-plugin#extracting-css-based-on-entry adresine bakın.


bu bugün varsayılan cevap olmalı
Giona Granata

8

Evet, bu mümkündür, ancak diğerlerinin söylediği gibi, bunu yapmak için ek paketlere ihtiyacınız olacaktır (package.json altındaki devDependencies öğesine bakın). İşte bootstrap SCSS -> CSS ve Bootstrap JS -> JS'mi derlemek için kullandığım örnek kod.

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

ek postcss.config.js dosyası:

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

Öğreticiye buradan bakın: https://florianbrinkmann.com/en/4240/sass-webpack


1

Diğerleri gibi bir eklenti kullanabilirsiniz.

ExtractTextPlugin kullanımdan kaldırıldı.

Web MiniCssExtractPluginpaketi yapılandırmanızda şu anda önerileni kullanabilirsiniz :

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

0

Ayrıca, daha az gereksinim ifadelerinizi giriş JS dosyanıza da koyabilirsiniz:

body.js'de

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

Sonra web paketinde

  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
})
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.