Why webpack doesn't render CSS from components to vendor.css file? - html

I use this template It works well. As you can see on the screen, all lybrarys (like bootstrap) render their CSS into vendor.css, but my component renders it into html directly, just into the header part in the html file in tag. Can you tell me how to configure it right?
// webpack.config.js
var isDevBuild = process.argv.indexOf('--env.prod') < 0;
var path = require('path');
var webpack = require('webpack');
var nodeExternals = require('webpack-node-externals');
var merge = require('webpack-merge');
var allFilenamesExceptJavaScript = /\.(?!js(\?|$))([^.]+(\?|$))/;
//var ExtractTextPlugin = require('extract-text-webpack-plugin');
// Configuration in common to both client-side and server-side bundles
var sharedConfig = {
resolve: { extensions: ['', '.js', '.ts'] },
output: {
filename: '[name].js',
publicPath: '/dist/' // Webpack dev middleware, if enabled, handles requests for this URL prefix
},
module: {
loaders: [
{ test: /\.ts$/, include: /ClientApp/, loader: 'ts', query: { silent: true } },
{ test: /\.html$/, loader: 'raw' },
{ test: /\.css$/, loader: 'to-string!css' },
{ test: /\.(png|jpg|jpeg|gif|svg)$/, loader: 'url', query: { limit: 25000 } },
{ test: /\.(jpg1)$/, loader: 'file?name=[name].[ext]' }
]
}
};
// Configuration for client-side bundle suitable for running in browsers
var clientBundleConfig = merge(sharedConfig, {
entry: { 'main-client': './ClientApp/boot-client.ts' },
output: { path: path.join(__dirname, './wwwroot/dist') },
devtool: isDevBuild ? 'inline-source-map' : null,
plugins: [
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require('./wwwroot/dist/vendor-manifest.json')
})
].concat(isDevBuild ? [] : [
// Plugins that apply in production builds only
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.optimize.UglifyJsPlugin()
])
});
// Configuration for server-side (prerendering) bundle suitable for running in Node
var serverBundleConfig = merge(sharedConfig, {
entry: { 'main-server': './ClientApp/boot-server.ts' },
output: {
libraryTarget: 'commonjs',
path: path.join(__dirname, './ClientApp/dist')
},
target: 'node',
devtool: 'inline-source-map',
externals: [nodeExternals({ whitelist: [allFilenamesExceptJavaScript] })] // Don't bundle .js files from node_modules
});
module.exports = [clientBundleConfig, serverBundleConfig];
and
// webpack.config.vendor.js
var isDevBuild = process.argv.indexOf('--env.prod') < 0;
var path = require('path');
var webpack = require('webpack');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var extractCSS = new ExtractTextPlugin('vendor.css');
module.exports = {
resolve: {
extensions: ['', '.js']
},
module: {
loaders: [
{ test: /\.(png|woff|woff2|eot|ttf|svg)(\?|$)/, loader: 'url-loader?limit=100000' },
{ test: /\.css(\?|$)/, loader: extractCSS.extract(['css']) }
]
},
entry: {
vendor: [
'#angular/common',
'#angular/compiler',
'#angular/core',
'#angular/http',
'#angular/platform-browser',
'#angular/platform-browser-dynamic',
'#angular/router',
'#angular/platform-server',
'angular2-universal',
'angular2-universal-polyfills',
'bootstrap',
'bootstrap/dist/css/bootstrap.css',
'es6-shim',
'es6-promise',
'jquery',
'zone.js',
'angular2-modal'
]
},
output: {
path: path.join(__dirname, 'wwwroot', 'dist'),
filename: '[name].js',
library: '[name]_[hash]',
},
plugins: [
extractCSS,
new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery' }), // Maps these identifiers to the jQuery package (because Bootstrap expects it to be a global variable)
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.DllPlugin({
path: path.join(__dirname, 'wwwroot', 'dist', '[name]-manifest.json'),
name: '[name]_[hash]'
})
].concat(isDevBuild ? [] : [
new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false } })
])
};

It seems like you are using style-loader to load your component css. You can change it to be the same loader (most likely file-loader) as the vendor.css in your webpack.config

If you compare the two css loaders in your config files, you can see that webpack.config.vendor.js has this line:
{ test: /\.css(\?|$)/, loader: extractCSS.extract(['css']) }
under loaders. That is the line that takes the CSS and puts it in its own file. So if you change the CSS loader for your webpack.config.js and make sure to add:
var extractCSS = new ExtractTextPlugin('styles.css'); // or name it whatever you want
at the top of the file. It should work.

Related

Created two Files in webpack build!!! How to disable it

I have been trying to use Webpack for several days.
And I encountered a problem in configuring.
This is my configuration now!(webpack config)
// Look for .html files
let htmlFiles = [];
let directories = ["src"];
while (directories.length > 0) {
let directory = directories.pop();
let dirContents = fs
.readdirSync(directory)
.map((file) => path.join(directory, file));
htmlFiles.push(...dirContents.filter((file) => file.endsWith(".html")));
directories.push(
...dirContents.filter((file) => fs.statSync(file).isDirectory())
);
}
module.exports = {
entry: "./src/index.js",
output: {
path: path.resolve(__dirname, "./dist"),
filename: "[name].[contenthash].js",
},
plugins: [
new CleanWebpackPlugin(),
new WebpackBar(),
new HtmlWebpackPlugin({
template: "./src/index.html",
hash: true,
filename: "index.html",
inject: "head",
scriptLoading: "defer",
xhtml: true,
}),
],
module: {
rules: [
//-------> CSS <-------//
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
generator: {
filename: "assets/styles/[name].[contenthash] [ext]",
},
},
//-------> HTML <-------//
{
test: /\.html$/i,
loader: "html-loader",
},
//-------> Images <-------//
{
test: /\.(png|jpe?g|gif)$/i,
type: "asset/resource",
generator: {
filename: "assets/images/[name].[hash][ext]",
},
},
//-------> Fonts <-------//
{
test: /\.(woff(2)?|ttf|eot)$/,
type: "asset/resource",
generator: {
filename: "./assets/fonts/[name].[contenthash][ext]",
But during construction, I see that two files are created from index.js...why??...how to disable it??
How fix it?
Thanks
Two created .js

Webpack creates empty image files with FileLoader

I've just created a template for a webapp using Webpack.
Unfortunatly whenever I'm building the App to dev or Prod, the File-Loader does not fix there references images and it creates empty files.
My config looks like this:
webpack.common.config
// noinspection WebpackConfigHighlighting
const path = require('path');
require('html-webpack-plugin');
module.exports = {
entry: {
vendor: path.join(__dirname, 'Source', 'Vendor.ts'),
main: path.join(__dirname, 'Source', 'Index.tsx')
},
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: '/node_modules/',
include: [
path.resolve(__dirname, 'Source')
],
},
{
test: /\.worker\.ts$/,
loader: 'worker-loader',
options: {
esModule: false,
}
},
{
test: /\.(svg|png|jpg|gif|ico)$/i,
use: {
loader: 'file-loader',
options: {
name: '[name].[hash].[ext]',
outputPath: "Images"
}
}
},
{
test: /\.html$/,
use: ['html-loader']
}
]
}
};
webpack.dev.config
const path = require('path');
const common = require('./webpack.config');
const merge = require('webpack-merge');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const {CleanWebpackPlugin} = require("clean-webpack-plugin");
module.exports = merge.merge(common, {
mode: 'development',
output: {
filename: '[name].[contenthash].js',
path: path.resolve(__dirname, 'Build')
},
plugins: [
new MiniCssExtractPlugin(
{
filename: '[name].[contenthash].css'
}
),
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, 'Source', 'template.html'),
filename: 'Index.html'
})
],
module: {
rules: [
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'sass-loader'
]
},
{
enforce: "pre",
test: "/\.js$/",
loader: "source-map-loader"
}
]
},
devtool: 'source-map'
});
Once this is build my Output Folder looks like this:
1a901b56586b6444ae11.ico <-- these should no be here have 0 byte
c4f9748e8b8d4038f05c.png <-- these should no be here have 0 byte
Index.html
main.90957f37ae16dde06736.js
main.90957f37ae16dde06736.js.map
main.cf18790244b83b75a490.css
main.cf18790244b83b75a490.css.map
vendor.1ce4fff9da8447255aaf.js
Images\Favicon.fba6e1cd14b7ac368970b6418b5c67ac.ico
Images\Logo.86047b7e6019c39da248c24c90924f8c.png
The references in the htmls change like this
template.html
<link rel="icon" href="Images/Favicon.ico">
...
<img src="./Images/Logo.png">
Index.html
<link rel="icon" href="1a901b56586b6444ae11.ico">
...
<img src="c4f9748e8b8d4038f05c.png">
I've tested this with the a template I found here were it worked:
https://github.com/Colt/webpack-demo-app

Trying to ''npm start" my vue.js build, but i get this error: This relative module was not found:

I'm trying to use node.js as my server and vue.js as my client side.
I'm building a chat application with both, with integrated stuff like Axios, Express, Sequelize and vuetify.
The project has been silent for a week of 2 due to a few complications.
I tried to start it back up again and i got this error on my server side:
ERROR Failed to compile with 1 errors 4:25:16 PM
This relative module was not found:
./src/main.js in multi (webpack)-dev-server/client?http://localhost:8081 webpack/hot/dev-server ./src/main.js
I've tried to change paths, restart servers and recreate files.
I'm quite new to Vue, so i have no clue what to do and i couldn't find an appropriate answer anywhere.
Here is the webpack.base.conf file
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
const createLintingRule = () => ({
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: [resolve('src'), resolve('test')],
options: {
formatter: require('eslint-friendly-formatter'),
emitWarning: !config.dev.showEslintErrorsInOverlay
}
})
module.exports = {
context: path.resolve(__dirname, '../'),
entry: {
app: './src/main.js'
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'#': resolve('src'),
}
},
module: {
rules: [
...(config.dev.useEslint ? [createLintingRule()] : []),
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}
]
},
node: {
// prevent webpack from injecting useless setImmediate polyfill because Vue
// source contains it (although only uses it if it's native).
setImmediate: false,
// prevent webpack from injecting mocks to Node native modules
// that does not make sense for the client
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty'
}
}```
It should just start the build like a regular app, but sadly.

Webpack 3.9.1 - How do I combine LESS files into one CSS file?

I'm very new to Webpack and I'm not certain how to handle LESS. I want to have many LESS files and I want them to compile into one CSS file after I run npm run build. This would result in a style.css file which includes everything.
My webpack.config.js looks like this:
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules:
[
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
},
{
test: /\.less$/,
use: [{
loader: "style-loader", // creates style nodes from JS strings
path: path.resolve(__dirname, 'src')
}, {
loader: "css-loader", // translates CSS into CommonJS
path: path.resolve(__dirname, 'src')
}]
},
{
test: /\.(png|svg|jpg|gif)$/,
use: [
'file-loader'
]
},
{
test: /\.json$/,
loader: 'json-loader'
}
]
},
plugins: [new HtmlWebpackPlugin()]
};
How exactly do I configure webpack to make it combine all LESS files into one CSS file?
You can use a plugin called extract-text-webpack-plugin to achieve this. According to their documentation, this plugin moves all the required *.css modules in entry chunks into a separate CSS file. So your styles are no longer inlined into the JS bundle, but in a separate CSS file (styles.css). Now of course, in your case, you will first have to parse your .less files to .css and then bundle them up into a single file.
You can modify your webpack config like so:
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: "css-loader"
})
},
{
test: /\.less$/,
use: ExtractTextPlugin.extract({ <---- Use the plugin here to extract the styles
fallback: "style-loader",
use: "css-loader"
})
},
{
test: /\.(png|svg|jpg|gif)$/,
use: ['file-loader']
},
{
test: /\.json$/,
loader: 'json-loader'
}
]
},
plugins: [
new HtmlWebpackPlugin(),
new ExtractTextPlugin("styles.css"),
]};
You can use extract-text-webpack-plugin to make one css file. But only do this for a production build not while you are developing.
I would look at using the Webpack less-loader. It covers a production build here

Reactjs hot-loader css files

I started new project with react-hot-boilerplate. Everything worked fine until i tried to add a css file to index.html.
<Link href="/style/main.css" rel="stylesheet">
Hot-loader doesnt read the css file. After some research i found out this line in server.js redirect all request to index.html
app.get('*', function(req, res) {
res.sendFile(path.join(__dirname, 'index.html'));
});
i changed it to
app.get('/', function(req, res) {
res.sendFile(path.join(__dirname, 'index.html'));
});
app.get('/style/main.css', function(req, res) {
res.sendFile(path.join(__dirname, 'style/main.css'));
});
and it worked. is there any better way to do that? do i need to map all the resources i servere.js?
I dont want to use style-loader or css-loader in webpack because i get a lot of errors and i cant simply use className="myCustomStyle".
var path = require('path');
var webpack = require('webpack');
var packageJSON = require('./package.json');
const PATHS = {
build: path.join(__dirname, 'target', 'classes', 'META-INF', 'resources', 'webjars', packageJSON.name, packageJSON.version)
};
module.exports = {
devtool: 'cheap-module-source-map',
resolve: {
extensions: ['', '.js', '.jsx', '.scss'],
alias: {
config: path.join(__dirname, 'src/config/dev.js'),
},
},
entry: [
'webpack-hot-middleware/client',
'./src/index'
],
output: {
path: PATHS.build,
filename: 'app-bundle.js',
publicPath: '/static/'
},
plugins: [
new webpack.HotModuleReplacementPlugin()
],
module: {
loaders: [{
test: /\.js$/,
loaders: ['react-hot', 'babel'],
include: path.join(__dirname, 'src')
}, {
test: /\.css$/,
loader: 'style-loader!css-loader?modules=true&localIdentName=[name]__[local]___[hash:base64:5]'
}]
}
};
Loading the static files should not be handled on server side. So you should not insert your styling or js files in server else the loading time would be more and since you are using react so all your files would be js so if you write the resource to be sent on the server then it's of no use. so the best option is to write loaders in webpack.
module: {
loaders: [
{
test: /\.jsx?$/,
loader: 'babel',
exclude: /(node_modules|bower_components)/
},
{
test: /\.css$/,
loader: 'style-loader!css-loader'
},
{
test: /\.scss$/,
loaders: ["style", "css", "sass"]
},
{
test: /\.json$/,
loader: 'json'
},
{
test: /\.(png|jpg)$/,
loader: 'file-loader'
}
]
}
If you want to do something like
<div className={styles.app}>
Then your component should be like
export default class Mycomponent extends Component{
let styles = {
app:{
'color': 'red',
}
}
return(){
render(
<div className={styles.app}>
)
}
}
This will solve your problem