Webpack how to use to merge css files? - javascript

I use Webpack to merge javascript files. But i do not understand how merge css files like javascript
var webpack=require('webpack');
module.exports = {
context: __dirname ,
entry: {one:["./script/born.js","./script/create_game.js"], two:["./css/destop.css", "./css/main_page.css"]},
output: {
path: __dirname,
filename: "/production/[name].js"
},
plugins: [
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
})
Is it possible to do such a thing?

To move every require("style.css") in entry chunks into a separate CSS file. And do not inline css into the JS bundle, but separate it in a CSS bundle file (styles.css). Use extract-text-webpack-plugin. There is an example from its documentation:
const ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallbackLoader: "style-loader",
loader: "css-loader"
})
}
]
},
plugins: [
new ExtractTextPlugin("styles.css"),
]
}
If you need to merge json data or some another data that may be converted to json by loaders chain use merge-webpack-plugin. If you need to join togather some more specific things use join-webpack-plugin.

Related

How to extract css as a separate .css file in Vite?

In webpack it is possible to generate output in such a way:
1 file with bundled js code
1 file with bundled css
This is part of the webpack config, that results in such output:
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
...
plugins: [
new MiniCssExtractPlugin({
filename: 'assets/css/styles.css',
chunkFilename: '[id].css',
}),
...
],
...
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
},
{
loader: 'css-loader',
},
],
},
...
How to achieve this with vite?
The vite templates by default generate config, where js and css are bundled into a single file and css is injected at runtime.

Webpack how to cache bust angular-translate with $translatePartialLoader?

"webpack": "^2.7.0"
I'm trying to add a hash to our translation files in order to cache bust when deploying. I've managed to extract the json and add a hash and output it to a folder and is good with the world.
But, my unhashed json is still under there original folders after building. I understand that we don't need to add a loader for json as it already has means of handling importing, so my question would be how do I clean out the json that's already been processed?
my folder structure is as follows
src/
app/
module-name/
/translations
en.json
fn.json
module-name/
/translations
en.json
fn.json
//ect...
I used the CopyWebpackPlugin to get the json and hash is there maybe an option ive missed that cleans out the process'd files? or maybe i'm approaching this the incorrect way.
const webpack = require('webpack');
const conf = require('./gulp.conf');
const path = require('path');
const VersionFile = require('webpack-version-file');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const pkg = require('../package.json');
const autoprefixer = require('autoprefixer');
module.exports = {
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'eslint-loader',
enforce: 'pre'
},
{
test: /\.(css|scss)$/,
loaders: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: 'css-loader?minimize!resolve-url-loader!sass-loader?sourceMap!postcss-loader'
})
},
{
test: /\.(jpe?g|png|gif|svg)$/,
loader: 'file-loader',
options: {
regExp: /\/([a-z0-9]+)\/[a-z0-9]+\.json$/,
name: '[name]-[hash].[ext]'
}
},
{
test: /\.js$/,
exclude: /node_modules/,
loaders: [
'ng-annotate-loader',
'babel-loader'
]
},
{
test: /\.html$/,
loaders: [
'html-loader'
]
}
]
},
plugins: [
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
new HtmlWebpackPlugin({
template: conf.path.src('index.html')
}),
new webpack.optimize.UglifyJsPlugin({
output: {comments: false},
compress: {unused: true, dead_code: true, warnings: false} // eslint-disable-line camelcase
}),
new ExtractTextPlugin('index-[contenthash].css'),
new webpack.optimize.CommonsChunkPlugin({name: 'vendor'}),
new webpack.LoaderOptionsPlugin({
options: {
postcss: () => [autoprefixer]
}
}),
new webpack.HashedModuleIdsPlugin(),
new CopyWebpackPlugin([{
from: 'src/app/**/*.json',
to: 'translations/[name]-[hash].[ext]'
}]),
new VersionFile({
output: `${conf.paths.dist}/version.txt`,
verbose: true
})
],
output: {
path: path.join(process.cwd(), conf.paths.dist),
filename: '[name]-[hash].js'
},
entry: {
app: [`./${conf.path.src('app/app.module.js')}`],
vendor: Object.keys(pkg.dependencies)
},
node: {
fs: 'empty',
/* eslint-disable camelcase */
child_process: 'empty'
}
};
Or to similfy the question, how can i add a hash to json files? and the following code doesn't seem to do anything.
{
test: /\.json$/,
loader: 'file-loader',
options: {
name: '[name]-[hash].[ext]'
}
}
EDIT:
so it seems like my json loader doesnt pick up the translation files as they're dynamicly imported like so how:
$translateProvider.useLoader('$translatePartialLoader', {
urlTemplate: 'app/{part}/translations/{lang}.json'
});
do you handle cases like this?
The main goal you're trying to do here is telling the browser its a new file when releasing a new version and we can do this fairly easily without having to force webpack to know what files are being used.
in your webpack config add this
const pkg = require('../package.json');
//...
new webpack.DefinePlugin({
__VERSION__: JSON.stringify(pkg.version)
})
and where you add your translation files this allows for the browser to know where has been a new release and should update translation files.
$translateProvider.useLoader('$translatePartialLoader', {
urlTemplate: `app/{part}/translations/{lang}.json?v=${__VERSION__}`
});

Webpack output bundle larger than expected

The only thing I have in my entry JS file is:
import $ from 'jquery';
The jQuery JS file has the size of 29.5kb from jsdelivr.
My entry, that only includes jQuery, and nothing else, has the size of 86kb.
webpack.config.js
const path = require('path');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
module.exports = {
entry: './src/js/scripts.js',
output: {
publicPath: "./dist/",
path: path.join(__dirname, "dist/js/"),
filename: "bundle.js"
},
watch: true,
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader",
query: {
presets: [
['env', { loose:true, modules:false }],
'stage-2'
],
plugins: [
['transform-react-jsx', { pragma:'h' }]
]
}
},
{
test: /\.pug$/,
use: [
"file-loader?name=[name].html&outputPath=../dist",
"extract-loader",
"html-loader",
"pug-html-loader"
]
},
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
use: ['css-loader?url=false', 'sass-loader']
})
},
]
},
resolve: {
alias: {
"TweenMax": path.resolve('node_modules', 'gsap/src/uncompressed/TweenMax.js'),
"TimelineMax": path.resolve('node_modules', 'gsap/src/uncompressed/TimelineMax.js'),
"animation.gsap": path.resolve('node_modules', 'scrollmagic/scrollmagic/uncompressed/plugins/animation.gsap.js'),
}
},
plugins: [
new ExtractTextPlugin('../css/main.css'),
new UglifyJsPlugin({
test: /\.js($|\?)/i
})
],
stats: {
warnings: false
}
};
I should also mention, that going into the output bundle.js it still has the jQuery comments.
jQuery JavaScript Library v3.3.1
https://jquery.com/ ...
Even though I'm calling webpack with the -p argument and have the UglifyJS plugin, but the rest of the file is minified and mangled. Any ideas?
Thanks!
Try to copy and paste minified jquery from your link. It's has size of 86.9 kb.
This link also show that jquery v3 minified file size is also around 80kb.
So you already have correct setup. Maybe your 29.5kb file size is minified+gzipped file.
The 29.5kb file size is definitely the minified+gzipped version as per the link Niyoko posted.
I would also recommend checking out Fuse-Box It brought down our project size from over 1mb to under 200kb (Vendor and App bundles combined). Very easy to get going as well and it is TypeScript first :) It takes the best features from a number of the more popular bundlers and brings them together and builds on those features.

Extracting sass as css using webpack

First. I know questions like this were asked, but I am missing something to understand them. I am trying to compile scss to css. And I would like webpack to basically do the same as sass app.scss : app.css. I tried to configure it using extract-text-webpack-plugin, but I am doing something wrong or missing smth.
It worked if I include(app.scss) in app.js but this makes no sense because if anyone has disabled JavaScript the styles won't work.
This is my webpack.config.js file. I have no idea how to do it.
const webpack = require("webpack");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
var jsConfig = {
entry: "./_dev/scripts/app.js",
output: { filename: "./scripts/bundle.js" },
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader"
}
]
}
};
var scssConfig = {
entry: "./_dev/scss/app.scss",
output: { filename: "./content/app.css" },
module: {
rules: [
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: "css-loader"
})
}
]
},
plugins: [
new ExtractTextPlugin({filename:"./_dev/scss/app.scss"}),
]
};
var config = [scssConfig, jsConfig];
module.exports = config;
Edit: I also found this. This series would have helped with all my questions so if you have similar questions make sure to read it before asking!
https://codeburst.io/simple-beginner-guide-for-webpack-2-0-from-scratch-part-v-495dba627718
You need to include your app.scss for webpack to be able to find your scss references because webpack will traverse your project and apply loaders to all files it can find through references starting from app.js recursively down. If you don't have references to app.scss somewhere in the project webpack can't find it and it won't build it. So in the entry of you project (assume it is app.js) you need to do this:
import 'relative/path/to/styles/app.scss';
But it doesn't mean that those who don't have js enabled won't receive your styles. You need to include app.scss only for the build phase of your project, after that your styles will be included in html and will be loaded even for those without js enabled.
webpack concepts section explains how webpack finds dependencies based on your entry point building its internal graph of dependencies.
Update:
There is a way that allows you to not add your app.scss in your js. You can include multiple files in your entry object in your webpack config. Here is an example of how configuration might look in your case:
const webpack = require("webpack");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
var config = {
entry: {
main: [
"./_dev/scripts/app.js",
"./_dev/scss/app.scss"
],
},
output: {
path: './scripts',
filename: "bundle.js"
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader"
},
{
test: /\.(css|scss)/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: ['css-loader', 'sass-loader']
})
}
]
},
plugins: [
new ExtractTextPlugin("./_dev/scss/app.scss"),
]
};
module.exports = config;
More information available on SO question webpack-multiple-entry-points-sass-and-js.
You also have incorrect configuration of ExtractTextPlugin in webpack. You are placing the whole path in the option for filename, which is not correct. In your case it should look like this:
plugins: [
new ExtractTextPlugin("./_dev/scss/app.css"),
]

Combining SCSS and CSS Into A Single File With WebPack

I'm a newbie to webpack and I'm having trouble understanding how I can take a bunch of scss files and css files and merge them together with webpack (After transpiling the sass of course).
With gulp, it was really obvious, as I can have 1 step the transpile the sass to css and then a step after that to concatenate them together.
However with webpack, it looks like everything happens at the same time.
This is a pretty basic requirement that I'm sure has an obvious answer to those more experienced.
I've got to the point where I can successfully output a transpiled scss to css and seperately output a css file from css input, but I can't figure out how to stick them together using webpack.
Below is my webpack.config.js file:
const path = require('path');
const webpack = require('webpack');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
const extractCSS = new ExtractTextPlugin('extractedCSS.css');
const extractSass = new ExtractTextPlugin({
filename: "extractedSASS.css",
disable: process.env.NODE_ENV === "development"
});
module.exports = function (env) {
return {
context: path.resolve(__dirname, './wwwroot/app'),
entry: {
main: './index.js',
vendor: 'moment'
},
output: {
filename: '[name].[chunkhash].js',
path: path.resolve(__dirname, './wwwroot/mytempdist')
},
module: {
rules: [{
test: /\.css$/,
use: extractCSS.extract({
use: 'css-loader'
})
},
{
test: /\.scss$/,
use: extractSass.extract({
use: [{
loader: "css-loader"
}, {
loader: "sass-loader"
}],
// use style-loader in development
fallback: "style-loader"
})
}
]
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function (module) {
// this assumes your vendor imports exist in the node_modules directory
return module.context && module.context.indexOf('node_modules') !== -1;
}
}),
//CommonChunksPlugin will now extract all the common modules from vendor and main bundles
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest' //But since there are no more common modules between them we end up with just the runtime code included in the manifest file
}),
//new webpack.optimize.UglifyJsPlugin({
// sourceMap: options.devtool && (options.devtool.indexOf("sourcemap") >= 0 || options.devtool.indexOf("source-map") >= 0)
//}),
extractSass,
extractCSS
],
devtool: 'inline-source-map'
}
}
How can I modify the above to make both the sass and css go into the file css output file?
Incase it makes a difference, below is an exerpt from my index.js file (entry point) toastr is an npm package and pace is just a normal downloaded css file:
var toastr = require('toastr');
import 'toastr/toastr.scss';
import pace from './../lib/pace/pace.min.js';
import './../lib/pace/pace.css';
You have 2 instances of ExtractTextPlugin defined with explicit names and you use those separate instances to load css and scss files respectively.
What you need is only 1 instance of the plugin which will accumulate all the CSS and only one rule for both scss and css files.
{
test: /\.s?css$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: ['css-loader', 'sass-loader']
})
}
This will handle both scss and css files and put it all in one single output CSS file.

Categories