vue + webpack project img cannot load static src - javascript

In my vue(2.0)+ webpack project, I config vue-html-loader, but in my .vue files img tag cannot load static src images.
Below is my webpack config:
module: {
loaders: [
...
{
test: /\.html$/,
exclude: /node_modules/,
loaders: ['html', 'html-minify']
}
, {
test: /\.vue$/,
loader: 'vue'
}
...
]
},
vue: {
...
html: {
root: path.resolve(__dirname, './source/static'),
attrs: ['img:src', 'img:srcset']
},
loaders: {
css: ExtractTextPlugin.extract("css"),
sass: ExtractTextPlugin.extract("css!sass")
}
},
resolve: {
root: [
path.resolve('./source')
],
extensions: ['', '.js', '.json', '.scss', '.html', '.css', '.vue'],
alias: {
'vue': 'vue/dist/vue.js'
}
},
Below is my .vue file:
<img src="/web/img/sieleLogo#1x.png" srcset="/web/img/sieleLogo#2x.png" />
My browser always come out 404 error. Did somebody get the same problem?

I have following in my webpack config, which works for me:
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue',
options: vueConfig
},
{
test: /\.js$/,
loader: 'babel',
exclude: /node_modules/
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'url',
options: {
limit: 10000,
name: '[name].[ext]?[hash]'
}
}
]
}
I have images in the src/assets folder which I can access and display without any specific setting.

I'd add an alias for your static img directory within your webpack aliases, i.e.
resolve: {
...
alias: {
'vue': 'vue/dist/vue.js',
'img': path.resolve(__dirname, '../web/img') // or wherever it is located relative to this file
}
}
now you can reference static images via ~img, i.e.
<img src="~img/sieleLogo#1x.png" srcset="~img/sieleLogo#2x.png" />
To ensure you can parse the above within your html you need to add the vue-html loader to your webpack config:
module: {
loaders: [
...
{
test: /\.html$/,
loaders: 'vue-html'
}
I would just replace your current html loader with the above.
However all this aside - due to the complexity of scaffolding a solid webpack vue application I'd strongely recommend you install the vue-cli: https://github.com/vuejs/vue-cli
Then you can simply roll out a tested and functioning webpack environment:
https://github.com/vuejs-templates/webpack
Simply copy your application into it. You'll likely have to do a bit of refactoring but the time saving on the set up is absolutely worth it.

Related

I wanted to dynamically import images but I run the project I do not see the images

I was creating react project and decided to escape create-react-app and create own custom template. So, then I wanted to dynamically add images via import like this
import picture1 from "../../assets/picture1.jpg";
import picture3 from "../../assets/picture3.jpg";
import picture5 from "../../assets/picture5.jpg";
So, to achieve that I installed file-loader and url-loader and set up the webpack config like this:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
// webpack will take the files from ./src/index
entry: "./src/index",
// and output it into /dist as bundle.js
output: {
path: path.join(__dirname, "/build"),
filename: "bundle.js",
},
// adding .ts and .tsx to resolve.extensions will help babel look for .ts and .tsx files to transpile
resolve: {
extensions: [".ts", ".tsx", ".js"],
},
module: {
rules: [
{
test: /\.(ts|tsx)$/,
enforce: "pre",
use: [
{
options: {
eslintPath: require.resolve("eslint"),
},
loader: require.resolve("eslint-loader"),
},
],
exclude: /node_modules/,
},
// we use babel-loader to load our jsx and tsx files
{
test: /\.(ts|js)x?$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
},
},
{
test: /\.(png|jpg|gif)$/i,
use: [
{
loader: "url-loader",
options: {
limit: 8192,
},
},
],
},
{
test: /\.(png|jpe?g|gif)$/i,
use: [
{
loader: "file-loader",
},
],
},
// css-loader to bundle all the css files into one file and style-loader to add all the styles inside the style tag of the document
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html",
}),
],
};
So, pls let me know if I did everything right? Why don't I see the image when I run the project?
You should remove the file-loader and use the url-loader instead. Including the limit option will cause all files over 8192 bytes to use file-loader. So including the file loader rule is redundant. Furthermore anything under 8192 will be converted into a data url and included in the bundle.js.
I would do something like this:
module.exports = {
...
rules: {
{
test: /\.jpe?g$|\.gif$|\.png$/,
use: [
{
loader: 'url-loader',
options: {
mimetype: 'image/png',
limit: 8192
}
}
]
}
}
}

How to handle import of SASS when building isomorphic React app?

I currently have the current setup for my React app with SSR support:
React app
Express server that compiles the React app via webpack
Using babel-node to run the Express app with ES6 features etc
Everything is working fine, I fire up the Express app and it compiles my React app etc. However - then I started to CSS modules to the React app, and then of course it all broke down, on the server side only of course. It does not know how to handle my .scss files when they are being imported in the React app.
If we forget about the CSS part, everything is working as I want it to. I can run the whole application in "dev-mode", where I have hot reloading etc, babel-node is transpiling my ES6 node code etc.
And I have setup a build script which is compiling the node source to valid ES5, and the React app gets bundled into a single file. All good.
But how should I be able to keep my setup, but with the CSS modules working without Node is complaining it does not understand that code?
My half-way-solution I came up with was when I build everything for production I tell babel to skip my serverRender.js file (which is the one that imports my App.js, uses renderToString etc, and instead compile that specific file with Webpack (using isomorphic-style-loader, css-loader etc), and outputs it in the right folder for my "server" folder/structure. That works, but it just feels wrong.
And then if I come back to running in dev mode, I basically have the same issue again, if I dont setup Webpack for that part of the development too...
Any one that can tell me the better way to do this setup?
I had the same issue working on isomorphic React app. Whatever I tried, I either had a problem described in here: SCSS compilation in an isomorphic React app or the error below:
Error: Module parse failed: Unexpected token (1:0)
You may need an appropriate loader to handle this file type.
I was able to solve the problem by adding isomorphic-style-loader package to my server configs in the webpack.
Here is the client configs for the webpack:
var browserConfig = {
//usual stuff
module: {
rules: [{
//... ,
{
test: /\.scss$/,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
options: {
modules: true, //turns on the CSS Module mode
importLoaders: 1,
localIdentName: '[name]__[local]___[hash:base64:5]', //generates CSS class names
sourceMap: true
}
},
{
loader: 'sass-loader'
}
]
}
]
}
};
And server configs:
var serverConfig = {
//...
module: {
rules: [{
//... ,
{
test: /\.scss$/,
use: [
{
loader: 'isomorphic-style-loader',
},
{
loader: 'css-loader',
options: {
modules: true,
importLoaders: 1,
localIdentName: '[name]__[local]___[hash:base64:5]',
sourceMap: true
}
},
{
loader: 'sass-loader'
}
]
}
]
},
}
With these configs in place, I was able to create styles.scss with simple styles:
$blueColor: #2196F3;
.component {
background: $blueColor;
}
Import it in the JS file:
import myStyles from './styles.scss';
And use it inside the React component in render():
<div className={ myStyles.component }>
This solution was kindly provided by DigitalKwarts, you can find more details about this solution here: https://blog.digitalkwarts.com/server-side-rendering-with-reactjs-react-router-v4-react-helmet-and-css-modules/
Let me know if it worked for you or of you were able to come up with a better solution.
I read #Galina answer and it's great. I set up a boilerplate using the article he has mentioned:
https://stackoverflow.com/a/68600509/6200607
Its config for webpack.config.js:
const path = require('path');
const isDevelopment = true;
module.exports = [
{
name: 'client',
target: 'web',
entry: './client.jsx',
output: {
path: path.join(__dirname, 'static'),
filename: 'client.js',
publicPath: '/static/',
},
resolve: {
extensions: ['.js', '.jsx']
},
devtool: 'source-map',
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /(node_modules\/)/,
use: [
{
loader: 'babel-loader',
}
]
},
{
test: /\.scss$/,
use: [
{
loader: 'style-loader',
},
{
loader: "css-loader",
options: {
modules: {
localIdentName: "[name]__[local]___[hash:base64:5]",
},
sourceMap: isDevelopment,
}
},
{
loader: 'sass-loader'
}
]
}
],
},
},
{
name: 'server',
target: 'node',
entry: './server.jsx',
output: {
path: path.join(__dirname, 'static'),
filename: 'server.js',
libraryTarget: 'commonjs2',
publicPath: '/static/',
},
devtool: 'source-map',
resolve: {
extensions: ['.js', '.jsx']
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /(node_modules\/)/,
use: [
{
loader: 'babel-loader',
}
]
},
{
test: /\.scss$/,
use: [
{
loader: 'isomorphic-style-loader',
},
{
loader: "css-loader",
options: {
modules: {
localIdentName: "[name]__[local]___[hash:base64:5]",
},
sourceMap: isDevelopment,
}
},
{
loader: 'sass-loader'
}
]
}
],
},
}
];

react production build, assets not loading

I am experiencing annoying problem, when i run my react app in development environment it all works ok, but when i try to build to production, all the links are wrong.
assume this tree:
main_directory
public/
svg/
some_img.svg
src/
components/
some_component.jsx
App.js
index.js
Now in some_component.jsx i am referencing svg file in this way:
src="/public/svg/some_img.svg"
however after building to production this path is untouched and therefore cannot access file anymore, as there i would need it to be changed to this:
src="svg/some_img.svg"
i was playing in the webpack config file, i thought that maybe by setting:
publicPath: "/"
to:
publicPath: "/public/"
would resolve the problem but the only thing it did was error during application start:
CANNOT GET/
my webpack config:
const HtmlWebPackPlugin = require("html-webpack-plugin");
const htmlPlugin = new HtmlWebPackPlugin({
template: "./public/index.html",
filename: "./index.html"
});
module.exports = {
output: {
filename: "main.[hash:8].js",
publicPath: "/"
},
module: {
rules: [
{
test: /\.jsx$/,
exclude: /node_modules/,
loader: "babel-loader?presets[]=react"
},
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.(sass|scss)$/,
use: ["style-loader", "css-loader", "sass-loader", "postcss-loader"]
},
{
test: /\.svg$/,
loader: "svg-sprite-loader"
}
]
},
plugins: [htmlPlugin],
devServer: {
historyApiFallback: {
rewrites: [{ from: /^\/$/, to: "/index.html" }]
}
},
resolve: {
extensions: [".js", ".jsx", ".json"]
}
};
How does one resolve this problem, so for both dev and production paths are unified?
How about importing the svg and then referencing the imported variable:
import someImg from "../../public/svg/some_img.svg"
src={someImg}
this is the solve for the question, config required for to specify path:
module: {
...
rules: [
{
test: /\.(png|jpg|gif|svg|ico)$/,
loader: 'file-loader',
query:{
outputPath: './img/',
name: '[name].[ext]?[hash]'
}
}
...
]
}

Webpack does not create output file (not using webpack-dev-server)

I am using webpack (NOT the dev-server, I know that doesn't output a file), and it is not creating a dist folder or output file.
I've tried running it directly through webpack (installed globally) and npm run build which uses a locally installed webpack. Neither work.
Here's my config:
const path = require('path');
module.exports = {
entry: {
app: './src/entry.js',
},
output: {
path: path.join('/dist'),
filename: '[name].bundle.js',
},
module: {
loaders: [
{
test: /\.tsx?$/,
loader: 'ts-loader',
},
{
test: /\.js$/,
exclude: /node_modules/,
loaders: ['ng-annotate'],
},
{
test: /\.js$/,
exclude: /(node_modules)/,
loader: 'babel', // 'babel-loader' is also a legal name to reference
query: {
presets: ['es2015', 'latest'],
},
},
{
test: /\.css$/,
loader: 'style-loader!css-loader',
},
{
test: /\.html$/,
loader: 'html',
},
{
test: /\.less$/,
loader: 'style!css!less',
},
],
},
resolve: {
extensions: ['', '.webpack.js', '.web.js', '.ts', '.tsx', '.js'],
root: [
path.resolve('./src'),
path.resolve('./node_modules'),
],
alias: {
vendor: path.join('/node_modules'),
},
fallback: ['node_modules'],
},
};
I've attempted to fix the problem by creating the dist folder manually, but that doesn't work either, the file still is not created.
The weird thing is that it DID build the file before, but now it's stopped. I've not changed the output location or the entry file at any point.
Any suggestions?
Your webpack output path is absolute:
output: {
path: path.join('/dist'), <----
filename: '[name].bundle.js',
},
My guess is it's being generated in your root directory. /dist would mean from the root of your file system, not relative to your project directory.
It should be:
output: {
path: path.join('./dist'),
filename: '[name].bundle.js',
},

Webpack load image inside of HTML

Somewhere in the middle of my Angular template I have img tag:
<img src="../../images/error.gif" />
Until now I was using raw-loader with this simple configuration:
test: /\.html/,
loader: 'raw'
But after i read this i decide I need a change:
The raw-loader is supposed to turn a text file into a CommonJS module
that exports the file contents as a string – nothing more.
What did I change:
So I changed my raw-loader to html-loader based on this article and this question.
{
test: /\.html$/,
loader: [
"html?" + JSON.stringify({
attrs: ["img:src", "img:ng-src"]
})
]
}
And this: loader
{ test: /.gif$/, loader: "file" }
Based on this and this questions I added publicPath: "/assets" to my webpackconfig.
And changed img tag on <img src=" { require('/assets/logo.png') } " />
My webpackconfig looks like:
webpack({
entry: path.resolve(__dirname, './main.js'),
output: {
path: dir_dist,
filename: 'custom-shared-lib.js',
publicPath: "/assets"
},
module: {
preLoaders: [
{
test: dir_bin,
loader: path.resolve(__dirname, "./my-loader.js"),
query: JSON.stringify(preLoaderQuery)
},
],
loaders: loader
},
plugins: [
// Avoid publishing files when compilation fails
new webpack.NoErrorsPlugin()
],
}, function(err, stats) {
console.log(stats.toString());
});
While variabile loaders are:
[
{
test: /\.js$/,
include: [dir_bin, dir_src],
loader: 'babel-loader',
query: {
presets: ['es2015']
}
},
{
test: /\.html$/,
loader: [
"html?" + JSON.stringify({
attrs: ["img:src", "img:ng-src"]
})
]
},
{ test: /.gif$/, loader: "file" }
]
Error:
This error happen while compiling:
Module not found: Error: Cannot resolve 'file' or 'directory' ./ {
require('/assets/error.gif') }
I would be happy for any advice.

Categories