funciona - javascript que es
¿Puedo usar webpack para generar CSS y JS por separado? (5)
¿Debería incluso usar webpack para activos que no sean JS si no los voy a mezclar en mi JS?
Tal vez no.
Webpack definitivamente está centrado en js, con la suposición implícita de que lo que está creando es una aplicación js.
Su implementación de
require()
permite tratar todo como un módulo (incluidos parciales Sass / LESS, JSON, prácticamente cualquier cosa) y automáticamente gestiona su dependencia por usted (todo lo que
require
está incluido y nada más).
¿por qué necesitaría MENOS en mi JS cuando no tiene nada que ver con mi código JS?
Las personas hacen esto porque están definiendo una parte de su aplicación (por ejemplo, un componente React, una Vista Backbone) con js.
Esa parte de la aplicación tiene CSS que va con ella.
Dependiendo de algún recurso CSS externo que se construye por separado y no se hace referencia directa desde el módulo js, es frágil, más difícil de trabajar y puede llevar a que los estilos se desactualicen, etc. Webpack lo alienta a mantener todo modular, por lo que tiene un CSS (Sass, lo que sea) parcial que va con ese componente js, y el componente js lo
require()
para aclarar la dependencia (para usted y para la herramienta de compilación, que nunca construye estilos que no necesita).
No sé si podría usar webpack para agrupar CSS por sí solo (cuando los archivos CSS no están referenciados desde ningún js). Estoy seguro de que podría conectar algo con complementos, etc., pero no estoy seguro de que sea posible de inmediato. Si hace referencia a los archivos CSS de su js, puede agrupar fácilmente el CSS en un archivo separado con el complemento Extraer texto, como usted dice.
Yo tengo:
- Archivos JS que quiero agrupar.
- MENOS archivos que quiero compilar a CSS (resolviendo @imports en un solo paquete).
Esperaba especificar esto como dos entradas separadas y tener dos salidas separadas (probablemente a través de extract-text-webpack-plugin). Webpack tiene todos los complementos / cargadores adecuados para hacer la compilación, pero no parece que le guste la separación.
He visto ejemplos de personas que requieren sus MENOS archivos directamente de JS, como
require(''./app.less'');
, por ninguna otra razón que decirle a webpack que incluya esos archivos en el paquete.
Esto le permite tener un solo punto de entrada, pero me parece realmente incorrecto: ¿por qué necesitaría MENOS en mi JS cuando no tiene nada que ver con mi código JS?
Intenté usar varios puntos de entrada, entregando tanto la entrada JS como el archivo LESS principal, pero cuando uso múltiples puntos de entrada, webpack genera un paquete que no ejecuta el JS en carga, lo agrupa todo, pero no sabe lo que debe ejecutarse al inicio.
¿Estoy usando mal el paquete web? ¿Debo ejecutar instancias separadas de webpack para estos módulos separados? ¿Debería incluso usar webpack para activos que no sean JS si no los voy a mezclar en mi JS?
Para aclarar aún más la respuesta anterior de bdmason, parece que la configuración deseable sería crear un paquete JS y CSS para cada página, así:
entry: {
Home: ["./path/to/home.js", "./path/to/home.less"],
About: ["./path/to/about.js", "./path/to/about.less"]
}
Y luego use el interruptor
[name]
:
output: {
path: "path/to/generated/bundles",
filename: "[name].js"
},
plugins: new ExtractTextPlugin("[name].css")
Configuración completa: con algunas adiciones no conectadas a la pregunta (en realidad estamos usando SASS en lugar 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
}
})
]
}
];
Sí, esto es posible, pero como otros dijeron, necesitará paquetes adicionales para hacerlo (vea devDependencies en package.json). Aquí está el código de muestra que utilicé para compilar mi SCSS bootstrap -> CSS y 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''
}
]
}
]
}
};
archivo adicional 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"
}
}
Vea el tutorial aquí: https://florianbrinkmann.com/en/4240/sass-webpack
Se puede generar un paquete CSS separado sin usar
require(''main/less)
en cualquiera de sus JS, pero como Brendan señaló en la primera parte de su respuesta, Webpack no está diseñado para que un paquete CSS global vaya junto con JS modular, Sin embargo, hay un par de opciones.
El primero es agregar un punto de entrada adicional para main.less, luego use el complemento Extraer texto para crear el paquete 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
})
]
};
El problema con este método es que también genera un archivo JS no deseado, así como el paquete, en este ejemplo:
style.js
que es solo un módulo Webpack vacío.
Otra opción es agregar el archivo less principal a un punto de entrada de Webpack existente:
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
})
]
};
Esto es ideal si solo tiene 1 punto de entrada, pero si tiene más, entonces su configuración de Webpack se verá un poco extraña ya que tendrá que elegir arbitrariamente a qué punto de entrada agregará el archivo principal menos.
También puede poner sus declaraciones Less require en su archivo JS de entrada también:
en body.js
// CSS
require(''css/_variable.scss'')
require(''css/_npm.scss'')
require(''css/_library.scss'')
require(''css/_lib.scss'')
Luego en 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
})