keep folder structure of source files in webpack - javascript

I have one .html page(index.html) and one entry point(index.js) and I want that dist folder keeps folder structure of my source files.
./webpack.config.js
./src/index/index.html
./src/index/index.js
./src/index/script1.js
./src/index/style1.scss
./src/assets/imgs/bg.jpg
I manage to write a webpack config file that works as I want but only when I use 'npm run build' and webpack give me a final build version.'
if I use 'npm run dev' then dev server opens a page that shows directories list.
How can I solve my problem?
this is my webpack.config.js
const webpack = require("webpack");
const path = require("path");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
module.exports = {
mode: 'development',
optimization: {
minimize: false
},
entry: {'index': './src/index/index.js'},
output: {
filename: '[name]/[name].js',
path: path.resolve(__dirname, './dist')
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader"
},
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: process.env.NODE_ENV === 'development',
reloadAll: true,
},
},
'css-loader',
'postcss-loader'
]
},
{
test: /\.scss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: process.env.NODE_ENV === 'development',
reloadAll: true,
},
},
'css-loader',
'postcss-loader',
'sass-loader'
]
},
{
test: /\.html$/,
exclude: /node_modules/,
use: [
{
loader: 'html-loader',
options: {
minimize: false,
publicPath: './'
}
}
]
},
{
test: /\.(png|jpg|jpeg)$/,
exclude: /node_modules/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'assets/imgs/',
publicPath: '../assets/imgs/'
}
}
]
},
]
},
plugins: [
new MiniCssExtractPlugin({
filename: "[name]/[name].css",
chunkFilename: '[id].css',
ignoreOrder: false
}),
new HtmlWebpackPlugin({
filename: 'index/index.html',
inject: true,
chunks: ['index'],
template: './src/index/index.html'
}),
new CleanWebpackPlugin()
]
};
package.json :
"scripts": {
"dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
"build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
}
I want dist folder to be like this :
./dist/index/index.html
./dist/index/index.js --> final .js bundle
./dist/index/index.css --> final .css bundle
./dist/assets/imgs/bg.jpg

Related

Heroku throws 403 forbidden after build with webpack

I have a problem with building my vuejs app on heroku after using my webpack config instead of simple using vue-cli-service build
package.json
"build": "webpack --config webpack.config.js",
//before webpack I use this
//"build": "vue-cli-service build",
after build with webpack my heroku build the whole app properly and I have this:
remote: -----> Compressing...
remote: Done: 92.6M
remote: -----> Launching...
remote: Released v69
remote: https://someapp.herokuapp.com/ deployed to Heroku
but when i go to https://someapp.herokuapp.com/, my app is blank and I have 403 Forbidden nginx :/
I do not know what is wrong with my webpack :/
here is my webpack config
webpack.config.js
var path = require('path')
const { VueLoaderPlugin } = require('vue-loader')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const CompressionPlugin = require("compression-webpack-plugin");
module.exports = {
entry: './src/main.js',
mode: 'production',
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'someapp.bundle.js'
},
optimization: {
usedExports: true,
minimize: true,
minimizer: [new UglifyJsPlugin()],
},
plugins: [
new VueLoaderPlugin(),
new MiniCssExtractPlugin({
filename: 'someapp.bundle.css'
}),
new OptimizeCSSAssetsPlugin(),
new CompressionPlugin({
test: /\.js(\?.*)?$/i,
algorithm: "gzip",
filename: "[path][base].gz"
})
],
module: {
rules: [
{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
],
},{
test: /\.vue$/,
loader: 'vue-loader'
},{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},{
test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
loader: 'file-loader?name=./fonts/[name].[ext]'
},{
test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
loader: 'file-loader?name=./fonts/[name].[ext]'
}, {
test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
loader: 'file-loader?name=./img/[name].[ext]'
}, {
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
loader: 'file-loader?name=./img/[name].[ext]'
}, {
test: /\.jpg$/,
use: ["file-loader?name=./img/[name].[ext]"]
}, {
test: /\.png$/,
use: ["file-loader?name=./img/[name].[ext]"]
}]
},
resolve: {
alias: {
'#': path.resolve('src')
},
extensions: ['*', '.js', '.vue', '.json']
},
devServer: {
historyApiFallback: true,
noInfo: true,
overlay: true
},
performance: {
hints: false
},
devtool: false
}
#EDIT:
I change build to vue-cli-service build and whole app was created successfully and a I do not have 403:Forbidden, so, problem must be with webpack
can someone tell me what is wrong with my heroku build?
thanks for any help!

React hot loader with webpack 5 loading whole page

I am pretty new to webpack and am confused by a range of answers. I have 3 components app.js, customButton, Sample.js whenever I change any text in any of the files the whole page is reloading. Can anyone help me out with webpack5 configuration if I have made any mistake.
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: "./src/index.js",
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, "./dist"),
clean: true,
publicPath: "/static/",
sourceMapFilename: "[name].bundle.js.map"
},
devServer: {
contentBase: path.resolve(__dirname, "./dist"),
overlay: {
errors: true,
warnings: true
},
inline: true,
index: "index.html",
port: 8080,
writeToDisk: true,
stats: {
chunks: false,
modules: false,
publicPath: false,
assets: false,
children: false,
colors: true
},
},
optimization: {
splitChunks: {
chunks: "all"
}
},
module: {
rules: [
{
test: /\.(png|jpe?g|gif)$/,
type: 'asset/resource'
},
{
test: /\.css$/,
use: [
'style-loader', 'css-loader'
]
},
{
test: /\.s[ac]ss$/,
use: [
'style-loader',
'css-loader',
'sass-loader'
]
},
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: [
{
loader: 'react-hot-loader/webpack',
},
{
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env', '#babel/preset-react'],
plugins: ['#babel/plugin-proposal-class-properties']
}
}
]
},
// {
// test: /\.js$/,
// exclude: /node_modules/,
// use: [
// {
// loader: 'babel-loader',
// options: {
// presets: ['#babel/env'],
// plugins: ['#babel/plugin-proposal-class-properties']
// }
// }
// ]
// }
],
},
plugins: [
new HtmlWebpackPlugin({
template: path.join(__dirname, "public", "index.html"),
}),
],
devtool: 'inline-source-map'
}`
My package.json scripts.
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --mode production --config webpack.prod.config.js",
"dev": "webpack serve --mode development --config webpack.dev.config.js --hot"
},
App.js
const App = () => {
return (
<div className="App">
<h2>Hi, Guyss !</h2>
<Suspense fallback={<div>Loading .. </div>}>
<CustomButton />
<Login />
</Suspense>
</div>
)
}
export default App;

Why PWA can be installed only in dev mode?

I'm trying to integrate PWA in my react project, when i run using webpack-dev-server i can see the PWA app that i can install in my computer, but when i build the project with webpack and try to run it, i can't do it anymore
webpack.config.js
const path = require("path");
const webpack = require("webpack");
const { styles } = require("#ckeditor/ckeditor5-dev-utils");
const MomentLocalesPlugin = require('moment-locales-webpack-plugin');
const BUILD_DIR = path.resolve(__dirname, "public");
const APP_DIR = path.resolve(__dirname, "src");
const envs = require('./config/envs').getEnv;
const plugins = require('./webpack-plugins');
module.exports = (env) => {
console.log("OUTPUT: env", env)
const config = envs(env.NODE_ENV);
const mode = env.production ? 'production' : 'development';
return {
mode,
entry: `${APP_DIR}/index.js`,
output: {
filename: "js/bundle.js",
path: BUILD_DIR,
publicPath: "/"
},
node: {
net: "empty",
tls: "empty",
dns: "empty",
fs: "empty"
},
module: {
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
exclude: /ckeditor5-[^/\\]+[/\\]theme[/\\].+\.css/
},
{
test: /\.js$/,
exclude: /node_modules/,
use: [
"babel-loader",
{
loader: "eslint-loader",
options: {
failOnError: true,
emitError: true,
emitWarning: true
}
}
]
},
{
test: /\.(graphql|gql)$/,
exclude: /node_modules/,
loader: "graphql-tag/loader"
},
{
test: /\.(jpg|png|gif|svg|pdf|ico)$/,
use: [
{
loader: "file-loader",
options: {
name: "[path][name]-[hash:8].[ext]"
}
}
],
exclude: [
/\.(js|jsx|mjs)$/,
/\.html$/,
/\.json$/,
/ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/,
/ckeditor5-[^/\\]+[/\\]theme[/\\].+\.css/
]
},
{
test: /ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/,
use: ["raw-loader"]
},
{
test: /ckeditor5-[^/\\]+[/\\]theme[/\\].+\.css/,
use: [
{
loader: "style-loader",
options: {
singleton: true
}
},
{
loader: "postcss-loader",
options: styles.getPostCssConfig({
themeImporter: {
themePath: require.resolve("#ckeditor/ckeditor5-theme-lark")
},
minify: true
})
}
]
}
]
},
devServer: {
historyApiFallback: true,
watchContentBase: true,
contentBase: "./public"
},
resolve: {
extensions: [".js"],
alias: {
src: path.resolve(__dirname, "src"),
shared: path.resolve(__dirname, "src", "shared"),
config: path.resolve(__dirname, "config"),
screens: path.resolve(__dirname, "src", "screens"),
package: path.resolve(__dirname, "package.json")
}
},
plugins: [
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin(),
new MomentLocalesPlugin({
localesToKeep: ['es-us', 'fr', 'es'],
}),
new webpack.DefinePlugin({
CONFIG: JSON.stringify(config),
}),
plugins.manifest,
plugins.sw
]
}
};
the Scripts on package.json
"build:local": "webpack --env.NODE_ENV=local --env.production --progress",
"start": "node server.js",
"dev": "webpack-dev-server --inline --watch --host 0.0.0.0 --env.NODE_ENV=local --env.development --progress"
Webpack packages used :
"webpack": "4.19.1",
"webpack-cli": "^2.0.15",
"webpack-dev-server": "^3.1.3",
"webpack-manifest-plugin": "^2.2.0"
PS: I tried both --env.production and --env.development in the build but neither worked
Any lead would be appreciated !
Making the app HTTPS fixed it, many thanks #Mathias

Maintain src folder structure into dist folder with Webpack?

I'm studying Webpack and I am facing this issue.
When i run the build task "npm run build", webpack creates the dist folder. The problem is that the dist folder doesn't respect the src folder, and Webpack puts all files into the root folder (the dist folder). So I have *.html pages near the style file and all the images. I want html files inside dist, images inside img (img inside dist) and so on...
This is my webpack.config.js file:
const path = require('path');
const HtmlWebPackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
},
{
test: /\.html$/,
use: [{
loader: 'html-loader',
options: {
minimize: true,
},
}],
},
{
test: /\.(css|scss)$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
importLoaders: 1,
sourceMap: true,
url: false,
minimize: true,
},
},
{
loader: 'postcss-loader',
options: {
sourceMap: true,
},
},
{
loader: 'sass-loader',
},
],
},
{
test: /\.(png|svg|jpg|gif)$/,
use: [{
loader: 'file-loader',
options: {
name: '[name].[ext]',
},
}],
},
],
},
plugins: [
new HtmlWebPackPlugin({
template: './src/index.html',
filename: 'index.html',
}),
new HtmlWebPackPlugin({
template: './src/work.html',
filename: 'work.html',
}),
new MiniCssExtractPlugin({
filename: '[name].[hash].css',
}),
new CleanWebpackPlugin(['dist']),
],
};
I found something on the Internet but all solutions didn't work.
Maybe I made something wrong? Please help me.
...
module: {
rules: [
...
{
test: /\.(png|svg|jpg|gif)$/,
use: [{
loader: 'file-loader',
options: {
name: 'img/[name].[ext]',
},
}],
},
],
},
plugins: [
...
new MiniCssExtractPlugin({
filename: 'styles/[name].[contenthash].css',
}),
],
};
You just add paths to the name

webpack reload styles without page refresh

I use webpack and livereload plugin but when I change something in styles, page refresh but I don't want it.
When I use gulp, I change anything in styles and save it and then css reload without page refresh.
Why does not work like gulp on webpack?
Codes are below
webpack.config.js
const path = require("path");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const WebpackNotifierPlugin = require("webpack-notifier");
const webpack = require("webpack");
const LiveReloadPlugin = require("webpack-livereload-plugin");
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const Dotenv = require('dotenv-webpack');
module.exports = {
entry: [
"./resources/js/app.jsx",
"./resources/scss/app.scss",
],
devtool: "source-map",
output: {
path: path.resolve(__dirname, "public/assets"),
filename: "js/app.js",
publicPath: "/public/assets/"
},
module: {
rules: [{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ["env", "react", 'stage-2']
}
}
}, {
test: /\.(scss)$/,
loader: ExtractTextPlugin.extract(['css-loader', 'sass-loader', "postcss-loader"])
}]
},
resolve: {
extensions: ["*", ".js", ".jsx"]
},
watch: true,
plugins: [
new CopyWebpackPlugin([{
from: "node_modules/bootstrap/dist",
to: "plugins/bootstrap"
}, , {
from: 'node_modules/font-awesome/css',
to: 'plugins/font-awesome/css',
}, {
from: 'node_modules/font-awesome/fonts',
to: 'plugins/font-awesome/fonts',
}]),
new WebpackNotifierPlugin({
alwaysNotify: true
}),
new webpack.LoaderOptionsPlugin({
debug: true
}),
new LiveReloadPlugin(),
new ExtractTextPlugin({
filename: 'css/app.css'
}),
new Dotenv({
path: './.env',
safe: true
}),
new webpack.EnvironmentPlugin(['NODE_ENV'])
],
node: {
fs: "empty"
}
};
package.json
"scripts": {
"start": "webpack-dev-server --history-api-fallback --progress --colors",
"dev": "cross-env NODE_ENV=development webpack --progress --color",
"prod": "cross-env NODE_ENV=production webpack -p --progress --color"
},
I use "npm run dev" command.
Where is the problem ?
ExtractTextPlugin sadly doesn't support hot module replacement.
From the page plugin description:
No Hot Module Replacement
what you need to do is use the plugin just in production.
rules: [
...
{
test: /\.scss$/,
use: process.env.NODE_ENV === 'production' ?
ExtractTextPlugin.extract([
"css-loader", "sass-loader", "postcss-loader"
]) : [
{ loader: "style-loader" },
{ loader: "css-loader" },
{ loader: "sass-loader" },
{ loader: "postcss-loader" }
]
}
]
Try like this it will work.
{
test: /\.(s*)css$/,
loader: ExtractTextPlugin.extract(['style-loader', 'css-loader', "sass-loader"])
}
If you share the package.json than it will be helpful for others to solve the issue.

Categories