issue with webpack-server 2 - webpack-dev-server

When i run webpack server, it redirects me to folders of project not my index.html, but if I open it without webpack server it works fine, and nothing in network tab. I think my webpack.config.js not loaded correctely!
my webpack.confing.js :
const ExtractTextPlugin = require("extract-text-webpack-plugin");
var path = require("path");
module.exports = {
entry : './src/app.js',
output : {
path : path.resolve(__dirname,'dist'),
filename : 'app.bundle.js'
},
module : {
rules : [
{test: /\.scss$/,
loader: ExtractTextPlugin.extract({
fallback: "style-loader",
use: ['css-loader','sass-loader'],
publicPath: "/dist"
})}
]
},
plugins: [
new ExtractTextPlugin({
filename: "app.scss",
disable: false,
allChunks: true
})
]
}

The problem is that you have misunderstood the public path concept that has nothing to do with file system path. That is, the publicPath is only related to the url.
url = `${host}:${port}${publicPath}${bundle}`
Only change your extract text plugin parameter publicPath for '/'

Related

Django webpack not loading images from static files

I'm in the process of making a website using django and react. I'm using client side rendering in react, instead of handling all the urls with django, and I stumbled upon the problem of not being able to refresh pages from urls other than the base url. From what I understood the easiest solution was webpack and it's historyApiFallback. Anyway, now that I've configured webpack, historyApiFallback doesn't work, and my static images will no longer load... Hopefully someone can help me out here, need it big time.
webpack.config.js
const path = require("path");
const BundleTracker = require('webpack-bundle-tracker');
const HtmlWebpackPlugin = require("html-webpack-plugin");
var config = {
context: __dirname,
entry: './src/index.js',
output: {
path: path.join(__dirname, 'assets/dist'),
filename: "main.js",
publicPath: '/'
},
devServer:{
historyApiFallback: true
},
plugins: [
new BundleTracker({ filename: './webpack-stats.json' }),
new HtmlWebpackPlugin({
template: './public/index.html'
})
],
devtool: 'hidden-source-map',
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: ['babel-loader'],
},
{
test: /\.css$/,
use: [
'style-loader', 'css-loader'
]
},
{
test: /\.(png|jpg|jpeg|gif)$/,
type: 'asset/resource',
use: [
'url-loader'
]
},
]
}
}
module.exports = () => {
return config
};
settings.py
FRONTEND_DIR = os.path.join(BASE_DIR, 'frontend')
STATIC_URL = 'static/dist/'
STATIC_ROOT = os.path.join(FRONTEND_DIR, "assets/dist/")
STATICFILES_DIRS = (
os.path.join(FRONTEND_DIR, "static/dist/"),
)
MEDIA_URL = '/Images/'
MEDIA_ROOT = os.path.join(FRONTEND_DIR, '/src/Images')
WEBPACK_LOADER = {
'DEFAULT': {
'BUNDLE_DIR_NAME': 'assets/dist/', # must end with slash
'STATS_FILE': os.path.join(FRONTEND_DIR, 'webpack-stats.json')
}
}
urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('', TemplateView.as_view(template_name='index.html')),
re_path(r'^api/news/', views.news_list),
path('api/news/<int:id>/', views.news_detail),
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
This is how my files look like: /assets/ is where the webpack bundle ends up and /static/ is the publicPath. It works fine with my js files and css files, they are all fetched correctly from /static/dist. However, my images and being fetched from /assets/dist/ and I'm getting 404 errors on all of them. I also have images that are uploaded via models and those work fine... Let me know if I need to add any more files/info and thanks in advance! Also, if anyone knows why my historyApiFallback isn't working, please tell me...
Second image is the error message when i try to fetch the image.

Why i get hashed .jpeg file when running 'npm run build' with webpack

Im a new beginner on develop react app.
Im trying to figure out how to set up my webpack.config.js file.
I have following ended up with this structure as you can see on the picture link below.
My question is: When im running 'npm run build' , its hashing the picture and put it into the /dist folder. How can i configure so it does not?
Because im using copyWebpackPlugin() to copy my images and push it to the dist folder, but i dont want the picture which i marked with arrow.
If anyone have some advice just bring it on.
This is how my webpack.config.js file look like:
const path = require("path");
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const CleanWebpackPlugin = require("clean-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
module.exports = {
entry: "./src/index.js",
mode: "development",
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /(node_modules|bower_components)/,
loader: "babel-loader"
},
{
test: /\.s?css$/,
loader: ["style-loader", "css-loader"]
},
{
test: /\.(jpe?g|png|gif|woff|woff2|eot|ttf|svg)(\?[a-z0-9=.]+)?$/,
loader: "url-loader?limit=100000"
}
]
},
resolve: { extensions: [".js", ".jsx"] },
output: {
path: path.resolve(__dirname, "dist/"),
filename: "bundle.js"
},
devtool: "cheap-module-eval-source-map",
devServer: {
contentBase: path.join(__dirname, "public/"),
proxy: {
"/api/*": {
target: "http://localhost:3000/",
secure: "true"
}
},
port: 4000,
publicPath: "http://localhost:4000/dist/",
hotOnly: true,
historyApiFallback: true
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new CleanWebpackPlugin(["dist"]),
new HtmlWebpackPlugin({
filename: "index.html",
template: "./public/index.html"
}),
new CopyWebpackPlugin([{ from: "public/images", to: "images" }])
]
};
I would suggest instead of copy-webpack-plugin use file-loader to copy images
{
test: /\.(png|jpg|gif|jpeg)$/,
use: [{
loader: 'file-loader',
options: {
name: 'images/[name].[ext]',
}
}]
}
if you want hash instead of name
name: 'images/[hash].[ext]',
Package
npm install --save-dev file-loader
It is because the url-loader has a default fallback to file-loader. So if your image is bigger than the limit you have set for url-loader, it does not rewrite the image to base64 data:image in your css, instead gives it to file-loader and it copies that image to your dist folder (output path).
So if you do not want this, disable the fallback option for url-loader
But I also think you should have configure your webpack to copy the files with file-loader properly instead that copy plugin. But you know...
I would give you an example based on your config but I am currently on mobile so I can't code right now.

URIError: Failed to decode param '/%PUBLIC_URL%/ WEBPACK

I have a problem running my react application with webpack, I have this error:
URIError: Failed to decode param '/%PUBLIC_URL%/src/css/TagsCheck.css'
at decodeURIComponent (<anonymous>)
and this is my webpack.config.js:
var debug = process.env.NODE_ENV !== "production";
var webpack = require('webpack');
var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
var publicUrl = '/public';
module.exports = {
context: path.join(__dirname, "src"),
devtool: debug ? "inline-sourcemap" : false,
entry: "./index.js",
devServer: {
host: '0.0.0.0',
port: 8080,
inline: true
},
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel-loader',
query: {
presets: ['react', 'es2015', 'stage-0'],
plugins: ['react-html-attrs', 'transform-decorators-legacy', 'transform-class-properties'],
}
}
]
},
output: {
path: __dirname + "/src/",
filename: "client.min.js"
},
plugins: debug ? [] : [
new webpack.optimize.DedupePlugin(),
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.optimize.UglifyJsPlugin({ mangle: false, sourcemap: false }),
// new HtmlWebpackPlugin({
// pkg: require("./package.json"),
// template: 'template.html',
// inject: false
// }),
// Makes the public URL available as %PUBLIC_URL% in index.html, e.g.:
// <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
new InterpolateHtmlPlugin({
PUBLIC_URL: publicUrl
// You can pass any key-value pairs, this was just an example.
// WHATEVER: 42 will replace %WHATEVER% with 42 in index.html.
}),
// Generates an `index.html` file with the <script> injected.
new HtmlWebpackPlugin({
inject: true,
template: path.resolve('public/index.html'),
}),
],
};
I want that in my index file can read the value of /%PUBLIC_URL%/.
What I have to do to make running my code?
And I have another question...
I am using react and I am importing the library react-native, Will I have some problem with the var PUBLIC_URL?
I can make the app easly only importing the 'react-native' library?
Thanks so much.
Regards,
It could be related to encoding of spaces (ISO hex %20) somewhere in your project, take a look at this Github issue comment: https://github.com/facebook/create-react-app/issues/4150#issuecomment-379742880
Disclaimer: I'm not familiar with how InterpolateHtmlPlugin() works and the best practices associated with it. However, I think that Babel is tripping up on the % char. What if you used the actual path instead. Maybe this answer will be of some help.
Another option would be to include the TagsCheck.css as part of the HtmlWebpackPlugin({ ... }) in your webpack config. Then that file would be copied to your output directory and the %PUBLIC_URL% should no longer be necessary to reference it as it would be in the root relative to the file that references it.
It may also be necessary to add another rule to your webpack.config.js:
//...
{
test: /\.css$/,
exclude: /node_modules/,
use: ['style-loader', 'css-loader']
// The filename should be preserved, if not then tack on ?name=[name].[ext] to either loader
// e.g. 'style-loader?name=[name].[ext]' ...
}
//...
Your setup is different enough from mine I could not test my suggestions. Sorry if I missed something and am way off. However, I hope they help someone!

Turn off hot reloading on webpack

I created a reactjs app with webpack. Everything works fine on local. Just by using npm start. I want to deploy a simple package for prod with webpack -p command. it gave me a bundle.js I appended it, and it works fine too. but it is still looking for my local server running as part of hot reloading config. I changed hot:false, but its still looking for it.
here is my webpack.config.js
var path = require('path');
var webpack = require('webpack');
module.exports = {
devtool: 'eval',
entry: [
'webpack-dev-server/client?http://csd.local.com:3000',
'webpack/hot/only-dev-server',
'./src/index'
],
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: '/static/'
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.DefinePlugin({'process.env.NODE_ENV': JSON.stringify('production')})
],
module: {
loaders: [{
test: /\.js$/,
loaders: ['react-hot', 'babel'],
include: path.join(__dirname, 'src')
},
{ test: /\.scss$/,
loaders: ["style", "css", "sass"],
include: path.join(__dirname, 'src')
}
]
}
};
And here is my server.js
var webpack = require('webpack');
var WebpackDevServer = require('webpack-dev-server');
var config = require('./webpack.config');
new WebpackDevServer(webpack(config), {
publicPath: config.output.publicPath,
hot: false,
historyApiFallback: true
}).listen(3000, 'localhost', function (err, result) {
if (err) {
return console.log(err);
}
console.log('Listening at http://csd.local.com:3000/');
});
All I want is, turn off hot reloading in prod.
That's because you're telling webpack to bundle HMRE's client-side scripts together with your app:
'webpack-dev-server/client?http://csd.local.com:3000',
'webpack/hot/only-dev-server',**strong text**
The solution would be to detect wether you're in "development" or "production" environment. To do so you can use "yargs" to parse your cli arguments (it's a webpack dependency so you don't even have to install it), and use the result to dynamically build your config.
var production = require('yargs').argv.p;
See a complete example at http://pastie.org/10895795

variable config file based on environment - reactjs, webpack

I need bunch of global variables in my reactjs components(example: hostnames, token, api urls, etc) based on the environment. but I don't want to add it to the js individually. I would like to create project.config file to set up prod:{hostname:example.com, api-url:prod, etc} and dev:{hostname:localhost.com, api-url:dev, etc}, I installed loose-envify, but I have to specify for each var.
var path = require('path');
var webpack = require('webpack');
var ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
devtool: 'eval',
entry: [
'webpack-dev-server/client?http://example.com:3000',
'webpack/hot/only-dev-server',
'./src/index'
],
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: '/static/'
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.DefinePlugin({'process.env.NODE_ENV': JSON.stringify('production')}),
new ExtractTextPlugin("static/super.css", {
allChunks: true
})
],
module: {
loaders: [{
test: /\.js$/,
loaders: ['react-hot', 'babel'],
include: path.join(__dirname, 'src')
},
{ test: /\.scss$/,
loaders: ["style", "css", "sass"],
include: path.join(__dirname, 'src')
}
]
}
};
Did you try to stringify a config json that can have some common and overridden properties for dev or prod?
Which will be given to the new webpack.DefinePlugin({...})?
I was trying to try something similar and tried following which seems to work fine.
In your webpack config add a DefinePlugin. Following is my webconfig:-
plugins: [
new BundleTracker({filename: './webpack-stats.json'}),
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify(process.env.environment),
}
})
],
Now while compiling use the following commands:-
environment=local webpack (for local)
environment=development webpack(for dev)
environment=production webpack(for prod)
Now if you see I have set 'NODE_ENV' with the cli input so when 'NODE_ENV' is production as value, the webpack automatically minifies your output bundle.
Now say you have API url declared in a file(I had Constants.jsx), so I added following to constants.jsx. So basically you can read the NODE_ENV set in webpack config in this Constants.jsx and import them in your components from where APIS are called by exporting it from here.
const api_url=function(){
let api_url='';
if(process.env.NODE_ENV == 'local'){
api_url= 'http://localhost:8002/api/v0';
}
else if(process.env.NODE_ENV == 'development'){
api_url = 'https://development/api/v0';
}
else if(process.env.NODE_ENV == 'production'){
api_url = 'https://production/api/v0';
}
return api_url;
}
export const url= api_url();
Hope it helped!

Resources