How to extract common.css from .less with webpack? - less

I have some entries with their own .less styles
I want to extract common css into common.css
entry: {
index: ['./client/js/index.js'],
login: ['./client/js/login.js']
},
module: {
loaders: [
....
{test: /\.css$/, loader: ExtractTextPlugin.extract('style', 'css')},
{test: /\.less$/, loader: ExtractTextPlugin.extract('style', 'css!less')}
....
]
},
plugins: [
new ExtractTextPlugin('css/[name].css'),
new webpack.optimize.CommonsChunkPlugin({
minChunks: 2,
name: 'common'
})
]
but I cant manage to generate common.css if I use .less files
If I use .css files - common.css is generated!
How can I get common.css from .less?

your webpack.optimize.CommonChunkPlugin settings should be "commons", "commons.js", like:
// ...
module.exports = {
// ...
plugins: [
new webpack.optimize.CommonsChunkPlugin("commons", "commons.js"),
new ExtractTextPlugin("[name].css")
]
}

Related

VueLoaderPlugin doies not return HTML used as inline loader for HtmlWebpackPlugin?

With the following webpack.common.js:
const pathtoresolve = require('path');
const paths = require('./paths')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')
module.exports = {
// Where webpack looks to start building the bundle
entry: [ 'whatwg-fetch', paths.src + '/main.js'],
resolve: {
extensions: [ '.js', '.vue' ],
alias: {
'components': pathtoresolve.resolve(__dirname, '../src/components/'),
'images': pathtoresolve.resolve(__dirname, '../src/images/'),
'styles': pathtoresolve.resolve(__dirname, '../src/styles/'),
}
},
// Where webpack outputs the assets and bundles
output: {
path: paths.build,
filename: '[name].bundle.js',
publicPath: '/',
},
// Customize the webpack build process
plugins: [
// Vue plugin for the magic
new VueLoaderPlugin(),
// Removes/cleans build folders and unused assets when rebuilding
new CleanWebpackPlugin(),
// Copies files from target to destination folder
new CopyWebpackPlugin({
patterns: [
{
from: paths.public,
to: 'assets',
globOptions: {
ignore: ['*.DS_Store'],
},
},
],
}),
// Generates an HTML file from a template
// Generates deprecation warning: https://github.com/jantimon/html-webpack-plugin/issues/1501
new HtmlWebpackPlugin({
title: 'webpack Boilerplate',
favicon: paths.src + '/images/favicon.png',
// TODO This isn't returning HTML. What did it return??
template: '!!vue-loader!' + paths.src + '/App.vue', // template file (explicitly vue)
filename: 'index.html', // output file
}),
],
// Determine how modules within the project are treated
module: {
rules: [
// JavaScript: Use Babel to transpile JavaScript files
{test: /\.vue$/, loader: 'vue-loader' },
{test: /\.js$/, exclude: /node_modules/, use: ['babel-loader']},
// Styles: Inject CSS into the head with source maps
{
test: /\.(scss|css)$/,
use: [
// Note: Only style-loader works for me !!!
// 'vue-style-loader',
'style-loader',
{loader: 'css-loader', options: {sourceMap: true, importLoaders: 1}},
{loader: 'postcss-loader', options: {sourceMap: true}},
{loader: 'sass-loader', options: {sourceMap: true}},
],
},
// Images: Copy image files to build folder
{test: /\.(?:ico|gif|png|jpg|jpeg)$/i, type: 'asset/resource'},
// Fonts and SVGs: Inline files
{test: /\.(woff(2)?|eot|ttf|otf|svg|)$/, type: 'asset/inline'},
],
},
}
I get the error:
$ yarn run client-build && yarn run serve
$ node client/build/app.js
building for production...
assets by status 751 KiB [cached] 4 assets
Entrypoint main = js/runtime.06de30f0b0451051a1b0.bundle.js styles/main.3b829f3c5154760383f9.css js/main.ec103c819b2711f469d3.bundle.js
ERROR in unable to locate 'D:\IdeaProjects\AIPlatform\oml\api\client\public' glob
ERROR in Error: The loader "D:\IdeaProjects\AIPlatform\oml\api\client\src\App.vue" didn't return html.
My vue template looks like:
<template>
<div id="app">
<router-view/>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
But the vue loader was invoked explicitly, so should be returning HTML from my Vue template.
This is using webpack#^5.8.0, html-webpack-plugin#^5.4.0, vue-loader#^15.9.8, and vue-template-compiler#^2.6.14 . (package.json would have been included, except StackOverflow refuses to allow posts that are too dense with code.)
My goal here is to get a html file out of this vue file using webpack. Any suggestions?
Any suggestions?

How can I use my static CSS with VueJS and webpack

I’m struggling a little with webpack, VUE and my CSS static files. See, I’d like to inject the styles that are in the Single File Components with the and I also want to have my static CSS file that has some useful classes. I’m running webpack 4 and I don’t clearly know how to approach the static CSS file situation.
This is my webpack config so far:
const path = require('path');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const WebpackMerge = require('webpack-merge');
const makeConfig = (mode) => require(`./build-utils/webpack.${mode}.js`)(mode)
const MiniCss = require('mini-css-extract-plugin');
module.exports = (env) => {
return WebpackMerge.merge(
{
mode: env.mode,
entry: './src/main.js',
output: {
filename: '[name].js',
publicPath: '/',
path: path.resolve(__dirname, './dist')
},
module: {
rules: [
{
test: /\.vue$/,
exclude: /node_modules/,
loader: 'vue-loader'
},
{
test: /\.(js)$/,
exclude: /node_modules/,
use: [
{ loader: 'babel-loader' }
]
},
{
test: /\.(css)/,
use: [
MiniCss.loader,
'css-loader'
],
include: /\assets\.css$/
},
{
test: /\.(css)/,
use: [
'style-loader',
'css-loader'
],
exclude: /\assets\.css$/,
},
{
test: /\.(png|jpg|gif|svg)$/i,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
esModule: false
}
}
]
}
]
},
plugins: [
new VueLoaderPlugin(),
new HtmlWebpackPlugin({
template: 'index.html'
}),
new MiniCss()
]
},
makeConfig(env.mode)
)
}
I have my statics css under /src/assets. Then my CSS assets gets imported in the entry point javascript’s file. The problem is that I don’t get my static CSS file emitted. What’s the solution for both: have my static css and the Single Component CSS.
Thank you!

Reference to assets from dist folder with vue + webpack in electron app

I am using vuejs + webpack + electron.
I have hard time retrieving the path to my asset.
My project structure is the following:
/my-project
/app
/components
componentA.vue
...
App.vue
main.js
/dist
/assets
/icons
/a.png
package.json
webpack.config.js
I load the static asset in the dist folder with file-loader.
My webpack.config.js looks like:
var path = require('path')
var webpack = require('webpack')
module.exports = {
entry: './app/main.js',
output: {
path: path.resolve(__dirname, './dist'),
filename: 'build.js'
},
module: {
rules: [
{
test: /\.vue$/,
use: {
loader: 'vue-loader',
}
},
{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
]
},
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015'],
plugins: ['transform-runtime']
}
}
},
{
test: /\.(jpe?g|png|gif|svg|ico)$/,
exclude: /node_modules/,
loader: "file-loader?name=/assets/icons/[name].[ext]"
},
]
},
resolve: {
alias: {
vue: 'vue/dist/vue.js'
}
},
plugins: [
new webpack.ExternalsPlugin('commonjs', [
'electron'
])
],
node: {
__dirname: true,
fs: 'empty',
module: 'empty',
net: 'empty',
tls: 'empty'
},
externals: ["fs"]
}
In the file componentA.vue I am trying to do the following:
<template>
<div>
<img :src= "link">
</div>
</template>
<script>
import Aa from '../assets/icons/a.png'
export default {
data () {
return {
link: '',
}
},
created() {
this.link = Aa;
},
...
</script>
But I have the following error:
Failed to load resource: net::ERR_FILE_NOT_FOUND file:///a.png
The images appear loaded in the correct path in the dist/assets/icons but electron is trying to load it from
file:///assets/icons/a.png
I'm new to webpack and tried to load it in different ways but i can't make it work, can you help me in resolving this issue ? Thanks a lot !

Vue SFC styles not being extracted in webpack production build

Trying to add vue (and SFCs) to my webpack app. The <template> and <script> blocks work fine, but for some reason the styles in the <style> block are not being extracted for production build.
In the dev build, it's extracting the .vue <style> block to a separate css file (named for the entrypoint). Which is OK but I'd prefer they went into my main stylesheet.
But no matter what I try, I can't get any .vue styles to show up (in any file) for the production build.
This is an abbreviated version of my webpack config:
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const VueLoaderPlugin = require("vue-loader/lib/plugin");
...
module.exports = (env) => {
return {
entry: {
app: ["./src/polyfills.js", "./src/scss/styles.scss", "./src/app.js"],
...
testview: "./src/js/views/TestView.js"
},
output: {
path: assets,
filename: "[name].[hash].js",
publicPath: "/static/"
},
resolve: {
modules: ["node_modules", "src"],
alias: {
vue$: "vue/dist/vue.esm.js"
},
extensions: ["*", ".js", ".vue"]
},
module: {
rules: [
{
test: /\.vue$/,
loader: "vue-loader"
},
{
test: /\.js?$/,
exclude: /node_modules/,
use: [
{
loader: "babel-loader",
options: {
presets: [
[
"#babel/preset-env",
{
targets: {
browsers: ["> 1%", "last 2 versions", "ie >= 11"]
}
}
]
],
plugins: ["#babel/plugin-proposal-class-properties"],
code: true,
comments: true,
cacheDirectory: true,
babelrc: false
}
}
]
},
{
test: /\.s?[ac]ss$/,
use: [
"vue-style-loader",
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
sourceMap: ifNotProduction()
}
},
{
loader: "postcss-loader",
options: {
ident: "postcss",
sourceMap: ifNotProduction(),
plugins: () =>
ifProduction([
require("autoprefixer")({
preset: "default"
}),
require("cssnano"),
require("css-mqpacker")
])
}
},
{
loader: "sass-loader",
options: {
sourceMap: ifNotProduction()
}
}
]
}
]
},
optimization: {
splitChunks: {
cacheGroups: {
commons: {
name: "commons",
chunks: "initial",
minChunks: 2,
minSize: 0
},
styles: {
name: "styles",
test: /\.css$/,
chunks: "all",
enforce: true
}
}
},
occurrenceOrder: true
},
plugins: [
new VueLoaderPlugin(),
new MiniCssExtractPlugin({
filename: "style.[hash].css"
}),
new HtmlWebpackPlugin({
hash: true,
inject: false,
template: "./src/jinja-templates/base.html.j2",
filename: `${templates}/base.html.j2`,
})
]
};
};
The .vue file I'm using is this demo one. I'm trying to import it into the entrypoint called 'testview' which contains simply:
import Vue from "vue";
import MainContent from "../components/main-content";
let MainComponent = Vue.extend(MainContent);
new MainComponent().$mount("#mainContent");
Did figure it out. I had to remove sideEffects: false from my package.json. This issue explains it further.
Still would like to know how to extract the .vue styles to my main stylesheet As it is now, the .vue styles are extracting to a separate stylesheet (dev and production).

how to use webpack split common business code?

I use webpack.optimize.CommonsChunkPlugin to Generate an extra chunk(vueCommon.js) which contains vuejs、vue-router、vue-resource...;but I want to Generate another business commonChunk like util.js。they are used just in some pages by "import ajax from '../service/service.js'";
problems after build:
every generated page.js has the code of service.js。
brief demos:
https://github.com/wxungang/vueJs
//webpack.base.js
"use strict";
var path = require('path');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
const CONFIG = require('./config');
var projectRoot = CONFIG.projectRoot || path.resolve(__dirname, '../');
var _ENV = CONFIG.env || 'dev';//prod
module.exports = {
devtool: _ENV != 'prod' ? '#eval-source-map' : false,
context: __dirname,//http://wxungang.github.io/1104/vue
entry: {
app: path.join(projectRoot, './vue/app.js'),
page: path.join(projectRoot, './vue/page.js')
},
output: {
path: path.join(projectRoot, './build/vue-' + _ENV),
publicPath: '',//'./build/vue-'+_ENV+'/',//path.join(__dirname, '../src/build/dev/')
filename: '[name].js',
chunkFilename: 'chunks/[name].chunk.js',
// crossOriginLoading: 'anonymous'
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.common.js',
'vue-router$': 'vue-router/dist/vue-router.common.js'
},
modules: ["node_modules"],
mainFiles: ["index", "app"],
extensions: [".js", ".json", '.vue']
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
// Since sass-loader (weirdly) has SCSS as its default parse mode, we map
// the "scss" and "sass" values for the lang attribute to the right configs here.
// other preprocessors should work out of the box, no loader config like this nessessary.
'scss': 'vue-style-loader!css-loader!sass-loader',
'sass': 'vue-style-loader!css-loader!sass-loader?indentedSyntax',
'less': 'vue-style-loader!css-loader!less-loader'
}
// other vue-loader options go here
}
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.less$/,
loader: "style-loader!css-loader!less-loader"
},
{
test: /\.scss$/,
loaders: ["style-loader", "css-loader", "sass-loader"]
},
{
test: /\.json$/,
loader: 'json-loader'
},
{
test: /\.html$/,
loader: 'vue-html-loader'
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]'
}
}
]
},
plugins: [
//注入一些全局变量
new webpack.DefinePlugin({
_ENV_: _ENV,
_VERSION_: JSON.stringify("1.0.0")
}),
new webpack.optimize.CommonsChunkPlugin({
name: "commons",
// (the commons chunk name)
filename: "vueCommons.js",
// (the filename of the commons chunk)
// minChunks: 2,
// (Modules must be shared between 3 entries)
// chunks: ["pageA", "pageB"],
// (Only use these entries)
// children: true,
// async: true,
}),
//可以和entry文件联合配置
new HtmlWebpackPlugin({
inject: false,
title: 'vueJs of app',
filename: 'app.html',
template: '../vue/entry/template.ejs',
scripts: ['./vueCommons.js', './app.js']
}),
new HtmlWebpackPlugin({
inject: false,
title: 'vueJs of page',
filename: 'page.html',
template: '../vue/entry/template.ejs',
scripts: ['./vueCommons.js', './page.js']
})
]
};
How did you use CommonsChunkPlugin to generate vueCommon.js?
A simple way is to add a new wepack entry like
utils: ['../service/service.js']
then add a new CommonsChunkPlugin instance in the webpack plugins array like this
new webpack.optimize.CommonsChunkPlugin('utils'),
the CommonsChunkPlugin will do the work by remove all utils module in other chunk files and generate only one utils.js.
Or you can just set minChunks option of the existing CommonsChunkPlugin into a number to wrap the vue file and utils together.