The images not loading from CSS file which is used for the background but in jsx it's loading
In the CSS file, I have used like below
.main-banner {
position: relative;
height: 910px;
z-index: 1;
background: transparent url(../../static/images/banner-bg1.jpg) right top no-repeat;
}
the image URL is absolutely fine
And configuration file like this
//next.config.js
const withImages = require('next-images');
const withCSS = require('#zeit/next-css')
module.exports = withImages(withCSS({
cssLoaderOptions: {
url: false
}
}))
what is the issue actually?
Thanks
Your static files are being deployed to the web's root. Same as your compiled js and css files.
So you can access them with the following url: url(/static/images/banner-bg1.jpg)
More information about that on this github issue.
I recieved [object Module] in css prop background-image. flag esModule: false in url-loader options fixed that problem.
const withCSS = require('#zeit/next-css');
const nextConfig = withCSS({
webpack(config, options) {
config.module.rules.push({
test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2)$/,
use: {
loader: 'url-loader',
options: {
limit: 100000,
esModule: false,
name: '[name].[ext]'
}
}
});
return config;
}
});
Related
With Nextjs the expected outcome is to see the Image component rendered as .WebP or .AVIF but it remains jpg -
Below is my next.config.js
/** #type {import('next').NextConfig} */
module.exports = {
images: {
domains: ['cdn.sanity.io'],
formats: ['image/avif', 'image/webp'],
},
reactStrictMode: true,
webpack(config) {
config.module.rules.push({
test: /\.svg$/,
use: [{ loader: '#svgr/webpack', options: { icon: true } }],
});
return config;
}, };
The following is the next/image component:
<Image
className="kitchen-img"
loader={myLoader}
loading="lazy"
layout="fill"
objectFit="cover"
src={urlFor(kitchen.mainImage).url()!}
alt={kitchen.title}
/>
Any idea why the it doesn't come up as avif/webp? What am I missing?
const myLoader = ({ src, width, quality }: any) => {
return `${src}?w=${width}&q=${quality || 85}` };
In your case, you are using a loader that will trigger the images directly from your CDN, and will not be stored in next cache folder.
To be 100% sure, try to remove the loader={myLoader} and check the network :) again. (test with next dev, and check if your image has webp extension)
If you still want to use webp, check if you can send the extension via your CDN.
const myLoader = ({ src, width, quality }: any) => {
return `${src}?w=${width}&q=${quality || 85}&?fm=webp`
};
Keep in mind, that some browsers don't support webp.
here is the code for my webpackconfig file.
const currentTask=process.env.nmp_lifecycle_event
const path = require("path")
const MiniCssExtractPlugin = require ('mini-css-extract-plugin')
const config=
{
entry:'./app/app.js',
output:{
filename:'myBundle.[hash].js',
path: path.resolve(__dirname,'dist')
},
plugins:[],
mode:'development',
devServer:{
port:8080,
static:path.resolve(__dirname, 'dist'),
hot:true
},
module:{
rules:[
{
test:/\.scss$/,
use:['style-loader', 'css-loader', 'sass-loader']
},
{
test:/\.js$/,
exclude:/(node_modules|bower_components)/,
use:{
loader:"babel-loader",
options:{
presets:['#babel/preset-env', '#babel/preset-react']
}
}
}
]
}
}
if(currentTask == "build"){
config.mode = "production"
config.module.rules[0].use[0]=MiniCssExtractPlugin.loader
config.plugins.push(new MiniCssExtractPlugin({filename:'main.[hash].css'}))
}
module.exports = config
I have tried your code and it works fine, you only have a typo in first line (wrong spelling for npm):
const currentTask=process.env.nmp_lifecycle_event
should be:
const currentTask=process.env.npm_lifecycle_event
Also, make sure that you have imported your .scss files somewhere in your javascript and that you are building your app with npm run build.
I have an MPA app, where vue.js is used as a part of the application. I have a very simple test set up, here:
relevant parts of my template
....
<div id='app-basket-checkout'>
<h1>Better Be Here</h1>
</div>
....
pageBasketCheckout.js (essentially my app.js)
import Vue from 'vue'
import AppBasketCheckout from './BasketCheckout.vue'
import './dummyScss.css'
Vue.config.productionTip = false
new Vue({
render: h => h(AppBasketCheckout)
}).$mount('#app-basket-checkout')
component
<template>
<div id="app-basket-checkout">
{{msg}}
</div>
</template>
<script>
export default {
name: 'AppBasketCheckout',
components: {
},
data() {
return {
msg: 'Hello'
}
}
}
</script>
<style scoped>
</style>
So the above code renders just fine in my front end. I end up with an extra div that has hello printed inside, well done.
However when I add css to the style tag:
<template>
<div id="app-basket-checkout">
{{msg}}
</div>
</template>
<script>
export default {
name: 'AppBasketCheckout',
components: {
},
data() {
return {
msg: 'Hello'
}
}
}
</script>
<style scoped>
body {
font-family: Arial, Helvetica, sans-serif;
line-height: 1.4;
}
</style>
This produces this error in chrome:
Uncaught Error: Cannot find module './BasketCheckout.vue?vue&type=style&index=0&id=2711cf65&scoped=true&lang=css&'
at webpackMissingModule (VM45512 BasketCheckout.vue:4)
at eval (VM45512 BasketCheckout.vue:4)
at Module../src/BasketCheckout.vue (pageBasketCheckout.bundle.js:40)
at __webpack_require__ (index.bundle.js:4312)
at eval (pageBasketCheckout.js:3)
at Module../src/pageBasketCheckout.js (pageBasketCheckout.bundle.js:29)
at __webpack_require__ (index.bundle.js:4312)
at checkDeferredModulesImpl (index.bundle.js:4453)
at webpackJsonpCallback (index.bundle.js:4435)
at pageBasketCheckout.bundle.js:9
Again this error only happens when adding css to the component. Here is my webpack.config.js:
const path = require('path');
const webpack = require('webpack')
const glob = require('glob')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
watch: true,
context: path.resolve(__dirname, 'uniquesite/uniquesite'),
mode: 'development',
entry: {
index: {
import: ['#babel/polyfill', './src/index.js'],
// dependOn: ['babel'],
},
pageProductDetails: {
import: ['#babel/polyfill', './src/pageProductDetails.js'],
dependOn: ['index'],
},
pageBasketCheckout: {
import: ['#babel/polyfill', './src/dummyScss.scss', './src/pageBasketCheckout.js'],
dependOn: ['index']
}
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'uniquesite/uniquesite/static/uniquesite/js/'),
},
plugins: [
new VueLoaderPlugin()
],
resolve: {
alias: {
jquery: "jquery/src/jquery",
'jquery-ui': "jquery-ui-dist/jquery-ui.js",
boostrap: "bootstrap/dist/js/bootstrap.bundle.js"
}
},
module: {
rules: [{
test: /\.vue$/,
loader: 'vue-loader'
},{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
]
},
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env']
}
}
}
]
}
};
You'll note I've also tried importing a dummy .css file to ensure the style loader works, as I've seen one more SO question with a similar problem that solved it that way. That didn't work for me however.
Update 1
My current thinking is that the problem has to be happening in the VueLoaderPlugin. That plugin is reponsible for splitting the script into distinct parts for template, logic, and style. It looks like the style is not actually making it into the bundle. See below.
"use strict";
eval(
"__webpack_require__.r(__webpack_exports__);
/* harmony import */
var _BasketCheckout_vue_vue_type_template_id_2711cf65___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(
/*! ./BasketCheckout.vue?vue&type=template&id=2711cf65& */
\"./src/BasketCheckout.vue?vue&type=template&id=2711cf65&\"
);
/* harmony import */
var _BasketCheckout_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(
/*! ./BasketCheckout.vue?vue&type=script&lang=js& */
\"./src/BasketCheckout.vue?vue&type=script&lang=js&\"
);
Object(function webpackMissingModule() {
var e = new Error(
\"Cannot find module './BasketCheckout.vue?vue&type=style&index=0&lang=css&'\"
); e.code = 'MODULE_NOT_FOUND';
throw e;
}());
/* harmony import */
var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(
/*! !../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */
\"../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"
);
/* normalize component */
var component = (
0,_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_3__.default
)(
_BasketCheckout_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__.default,
_BasketCheckout_vue_vue_type_template_id_2711cf65___WEBPACK_IMPORTED_MODULE_0__.render,
_BasketCheckout_vue_vue_type_template_id_2711cf65___WEBPACK_IMPORTED_MODULE_0__.staticRenderFns,
false,
null,
null,
null)
/* hot reload */
if (false) { var api; }
component.options.__file = \"src/BasketCheckout.vue\"
/* harmony default export */
__webpack_exports__[\"default\"] = (component.exports);
//# sourceURL=webpack:///./src/BasketCheckout.vue?"
);
Scoped CSS rules only apply to the current component (and its child components' root nodes).
You are mounting your Vue instance at #app-basket-checkout, which is already inside a <body> element.
You can style <body>, but do it using a global stylesheet that is imported in your app.js, not a subcomponent.
Alternatively, you can apply a class-based style at a low level node within your Vue instance and likely deliver your desired styles.
I am creating an app in Svelte and I have a problem with styles.
I preprocess imports in style tags using the rollup.config.js file, not with svelte-preprocess, but with rollup-plugin-svelte preprocess.
I do it following the example of the official docs. https://svelte.dev/docs#svelte_preprocess
Everything works fine, in the sass return code: css.toString(); I get the css code from my imports, but the result is not added to my bundle.css, it just disappears.
What am I missing?
My rolling.config.js is:
...
...
plugins: [
svelte({
dev: !production,
css: css => {
css.write('public/build/bundle.css');
},
preprocess: {
style: async ({ content, attributes, filename }) => {
// only process <style lang="sass">
if (attributes.lang !== 'sass') return;
const { css, stats } = await new Promise((resolve, reject) => sass.render({
file: filename,
data: content,
includePaths: [
path.dirname(filename),
'./node_modules',
],
}, (err, result) => {
if (err) reject(err);
else resolve(result);
}));
return {
code: css.toString(), // this works
dependencies: stats.includedFiles
};
}
},
}),
resolve({
browser: true,
dedupe: ['svelte']
}),
...
...
In one of my .svelte files
<style lang="sass">
#import './styles/App.scss';
</style>
All other styles without the lang = "sass" attribute are not preprocessed and are added to the bundle.css file.
I'm blocked, does anyone help me?
Add emitCss: true in svelte(..) like this :
svelte({
dev: !production,
emitCss: true, // without this, <style> in components are not included in bundle
css: css => {
css.write('public/build/bundle.css')
}
}),
This will emit CSS as "files" for other plugins to process.
Use the default svelte template that renders css to add css support appropriately... For further details check https://github.com/sveltejs/template/blob/master/rollup.config.js
set bundle.css as indicated
I have a few SCSS theme files I want to extract to CSS files and later load them into the page. I want to be able to use contenthash for long term caching.
Since I'm using Webpack 4, I am also using mini-css-extract-plugin. I started down the path of creating a splitChunks in my webpack config.
// webpack.config.js
module.exports = {
plugins: [
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: "[name].[contenthash].css",
chunkFilename: "[id].[contenthash].css"
})
],
optimization: {
splitChunks: {
cacheGroups: {
'vendor': {
// custom commons chunk for js
},
'theme-a': {
test: /theme-a.\scss/,
},
'theme-b': {
test: /theme-b.\scss/,
},
// more themes
}
}
}
module: {
rules: [
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
"sass-loader"
]
}
]
}
}
I've then tried dynamically importing the css in my app:
// app.js
class App extends React.Component {
// constructor
login(themeName) {
import(/* webpackChunkName: "`${themeName}`" */ `./path/to/${themeName}.scss`).then(theme => {
// do something with `theme`
}
}
// other stuff
}
I need to be able to load that css file dynamically in login() and I'm just not sure how to reference it when it has a generated [contenthash].
TLDR: Is there a good way to both extract css and import the referenced CSS bundle to lazy load later? I'm not tied to mini-css-extract-plugin.
Edit: Created a mini-css-extract-plugin issue here.
My solution ended up using extract-text-webpack-plugin. My config now looks like this:
// webpack.config.js
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const ExtractThemeA = new ExtractTextPlugin({ filename: 'themeA.[hash].css', allChunks: true});
module.exports = {
plugins: [
ExtractThemeA,
// more plugins for other css files
],
optimization: {
splitChunks: {
cacheGroups: {
// Note: No changes to splitChunks
'vendor': {
// custom commons chunk for js
}
}
}
module: {
rules: [
{
test: /theme-a\.scss$/,
use: ExtractThemeA.extract([ 'css-loader', 'sass-loader' ])
},
// more module rules for each css file needed
]
}
}
Then, these chunks are available by file name in my HtmlWebpackPlugin:
<!-- HtmlWebpackPlugin Template -->
<script>
// provides me with an array of file name strings
var themesManifest = <%= htmlWebpackPlugin.files.css %>
</script>
Sorry for my miss understanding,
You could probably just make two different scss-files and import them as needed. theme.scss admin.scss or like so
This is how I am doing scss in React right now
In App.js
import styles from '../../stylesheet/main.scss'
// could be as well
import styles1 from '../../stylesheet/theme.scss' // some file
import styles2 from '../../stylesheet/admin.scss' // some other file
const App = () => {
<div className={styles.action_feed} >{ content }</div>
}
In main.scss
.action_feed {
position: fixed;
width: 350px;
height: auto;
max-height: 100%;
max-width: 100%;
top: 0;
left: 0;
z-index: 9999;
}
I think you could just as well do it like so
const themeName = 'main'
import(`./stylesheet/${themeName}.scss`, (css) => {
// meaby set this to state? not quite sure how should properly handle
// dynamically imported css
this.setState({ css: css.action_feed })
// or possible this way. I have done some non-React dom manipulation
// this way before
document.querySelector('body').classList.add(css.action_feed)
})
<div className={this.state.css}>{ content }</div>
You should probably check out React's new Refs API as well. It might give you some nice flexibility for giving className-attr to required element.
Having set to splitChunks.chunks to all works though i think in this case anyway