나는 가지고있다:
- 번들하려는 JS 파일.
- CSS로 컴파일하려는 파일이 적습니다 (@imports를 단일 번들로 해결).
나는 이것을 두 개의 개별 입력으로 지정하고 두 개의 개별 출력을 갖기를 원했습니다 (아마도 extract-text-webpack-plugin을 통해). Webpack에는 컴파일을 수행 할 수있는 모든 적절한 플러그인 / 로더가 있지만 분리를 좋아하지 않는 것 같습니다.
나는 require('./app.less');
웹팩에 번들에 파일을 포함하도록 지시하는 것 외에 다른 이유없이 JS에서 직접 LESS 파일을 요구하는 사람들의 예를 보았습니다 . 이것은 당신이 하나의 진입 점만을 가질 수있게 해준다. 그러나 그것은 나에게 정말로 잘못된 것처럼 보인다. 내 JS 코드와 아무 관련이 없는데 왜 내가 JS에서 LESS를 덜 요구 할까?
여러 진입 점을 사용하여 항목 JS와 기본 LESS 파일을 모두 전달했지만 여러 진입 점을 사용할 때 webpack은로드시 JS를 실행하지 않는 번들을 생성합니다. 시작시 실행해야하는 것.
웹팩을 잘못 사용하고 있습니까? 이러한 개별 모듈에 대해 별도의 웹팩 인스턴스를 실행해야합니까? JS에 혼합하지 않을 경우 비 JS 자산에도 웹팩을 사용해야합니까?
답변
JS에 혼합하지 않을 경우 비 JS 자산에도 웹팩을 사용해야합니까?
아마. Webpack은 확실히 js 중심이며, 빌드중인 것이 js 응용 프로그램이라는 암시 적 가정이 있습니다. 의 구현을 require()
통해 모든 것을 모듈 (Sass / LESS 부분, JSON, 거의 모든 것 포함)으로 처리하고 자동으로 종속성 관리를 수행 할 수 있습니다 ( require
번들 된 모든 것 , 다른 것은 없음).
내 JS 코드와 관련이 없는데 왜 내 JS에서 LESS가 덜 필요합니까?
사람들은 js로 애플리케이션의 일부 (예 : React 컴포넌트, Backbone View)를 정의하기 때문에이를 수행합니다. 응용 프로그램의 해당 부분에는 CSS가 있습니다. 별도로 빌드되고 js 모듈에서 직접 참조되지 않는 일부 외부 CSS 리소스에 따라 깨지기 쉽고 작업하기가 더 어렵고 스타일이 최신 상태가 될 수 있습니다. Webpack은 모든 것을 모듈 식으로 유지하도록 권장하므로 CSS가 있습니다. (Sass, 무엇이든) 해당 js 구성 요소와 함께 제공되는 부분이며 js 구성 요소 require()
는 종속성을 명확하게하기 위해 (필요하지 않은 스타일을 결코 빌드하지 않는 빌드 도구)입니다.
웹팩을 사용하여 CSS를 자체적으로 번들링 할 수 있는지 모르겠습니다 (CSS 파일이 어떤 js에서도 참조되지 않는 경우). 나는 당신이 플러그인 등으로 무언가를 연결할 수 있다고 확신하지만, 그것이 상자 밖에서 가능하다는 것은 확실하지 않습니다. js에서 CSS 파일을 참조하는 경우 말했듯이 Extract Text 플러그인을 사용하여 CSS를 별도의 파일로 쉽게 묶을 수 있습니다.
답변
require('main/less)
JS에서 사용하지 않고 별도의 CSS 번들을 생성 할 수 있지만 Brendan이 답변의 첫 부분에서 지적했듯이 Webpack은 모듈 식 JS와 함께 사용할 전역 CSS 번들을 위해 설계되지 않았지만 몇 가지 옵션이 있습니다. .
첫 번째는 main.less에 대한 추가 진입 점을 추가 한 다음 Extract Text 플러그인을 사용하여 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
})
]
};
이 방법의 문제점은 원치 않는 JS 파일과 번들도 생성한다는 것입니다.이 예제 style.js
에서는 빈 Webpack 모듈 일뿐입니다.
또 다른 옵션은 기존 Webpack 진입 점에 main less 파일을 추가하는 것입니다.
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 개 뿐인 경우 이상적이지만 더 많은 경우 기본 파일을 추가 할 진입 점을 임의로 선택해야하므로 Webpack 구성이 약간 이상하게 보입니다.
답변
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
}
})
]
}
];
답변
mini-css-extract 플러그인이있는 webpack 4 솔루션
웹팩 팀은 추출 텍스트 플러그인보다 mini-css-extract 사용을 권장합니다.
이 솔루션을 사용하면 css 항목 만 포함하는 별도의 청크를 만들 수 있습니다.
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'
}),
]
};
저는이 접근 방식이 모듈식이 아니라는 것을 알고 있지만 빌드 할 기반을 제공해야하며 자바 스크립트와 CSS를 혼용하지 않으려는 프로젝트에서 웹팩을 채택하기위한 훌륭한 전략입니다.
이 접근 방식의 단점은 css-loader가 여전히 추가 javascript 파일을 생성한다는 것입니다 (사용 여부에 관계없이). 이것은 아마도 webpack 5에서 수정 될 것 입니다.
JS에 혼합하지 않을 경우 비 JS 자산에도 웹팩을 사용해야합니까?
나는 이것에 잘못된 것이 없다고 생각하지만 궁극적으로 여러 빌드 시스템을 관리하는 데 대한 관용에 달려 있습니다. 나에게 이것은 과잉처럼 느껴지므로 웹팩 생태계에 남아있는 것이 선호됩니다.
위에 설명 된 전략에 대한 자세한 내용은 https://github.com/webpack-contrib/mini-css-extract-plugin#extracting-css-based-on-entry 를 참조 하십시오.
답변
예, 가능하지만 다른 사람들이 그렇게하려면 추가 패키지가 필요하다고 말했습니다 (package.json 아래의 devDependencies 참조). 다음은 부트 스트랩 SCSS-> CSS 및 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'
}
]
}
]
}
};
추가 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 에서 자습서를 참조하십시오.
답변
다른 사람들이 언급했듯이 플러그인을 사용할 수 있습니다.
ExtractTextPlugin
더 이상 사용되지 않습니다.
현재 권장 MiniCssExtractPlugin
되는 웹팩 구성을 사용할 수 있습니다 .
module.exports = {
entry: {
home: ['index.js', 'index.less']
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css',
}),
]
}
답변
Less require 문을 항목 JS 파일에 넣을 수도 있습니다.
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
})