Heroku throws 403 forbidden after build with webpack - javascript

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!

Related

Why is webpack trying to bundle my test files?

I have two main directories in my project: "src" and "specs".
The entrypoint of my webpack configuration is set to a file within src. Also the context of the webpack config is set to the src directory. I have a postinstall hook in my package.json which bundles the app into a dist folder whenever the package is installed via "npm install". This also means that the devDependencies are not installed and that is what causes my npm install to fail. Apparently webpack tries to process the files in specs which it cannot do because the devDependencies are not installed.
Any idea why webpack thinks it should process the files in the specs directory?
Here is my complete webpack config:
const path = require("path");
const nodeExternals = require("webpack-node-externals");
const NODE_ENV = "development";
const client = {
entry: path.join(__dirname, "src", "browser_sdk", "index.ts"),
context: path.resolve(__dirname, "src", "browser_sdk"),
target: "web",
mode: NODE_ENV,
devtool: "source-map",
watch: false,
output: {
path: path.resolve(__dirname, "dist"),
filename: "client.js",
library: {
type: "umd",
},
},
module: {
rules: [
{
test: /\.ts$/,
use: "ts-loader",
exclude: /node_modules.*\.js$/,
},
],
},
resolve: {
extensions: [".tsx", ".ts", ".js"],
},
externals: {
"pg-native": "require('pg-native')"
},
optimization: {
minimize: false,
},
};
const server = {
entry: path.join(__dirname, "src", "server", "index.ts"),
context: path.resolve(__dirname, "src", "server"),
mode: NODE_ENV,
target: "node",
externals: [nodeExternals(), 'pg-native'],
watch: false,
devtool: "source-map",
output: {
path: path.resolve(__dirname, "dist"),
filename: "server.js",
library: {
type: "umd",
},
},
resolve: {
extensions: [".ts", ".js"],
},
module: {
rules: [
{
test: /\.ts$/,
use: "ts-loader",
exclude: /node_modules.*\.js$/,
},
],
},
};
module.exports = [server, client];
The following config fixed my problems. I used transpileOnly to prevent the specs directory is bundled and I wrote a custom exclude handler to prevent node_module is bundled.
module: {
rules: [
{
test: /\.tsx?$/,
use: {
loader: "ts-loader",
options: {
transpileOnly: true
},
},
exclude: (e) => {
let file = e.replace(__dirname, '.');
return file.match(/node_modules/)
}
},
],
},

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

Webpack not generating bundle when used with Webpack Dev Server

I have a webpack configuration that generates the react bundle when i call webpack directly.
Since i would like to incorporate hot reloading i need to run the webpack dev server alongside my development express server (serving API endpoints) that runs on port 3000
webpack.dev.config.js
const webpack = require('webpack');
const merge = require('webpack-merge');
const Jarvis = require('webpack-jarvis');
const path = require("path");
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = merge({}, {
mode: 'development',
devtool: 'cheap-module-eval-source-map',
output: {
chunkFilename: '[name]-[hash].js',
publicPath: "http://localhost:3000/build/",
crossOriginLoading: 'anonymous'
},
optimization: {
noEmitOnErrors: true,
namedModules: true,
},
plugins: [
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
new HtmlWebpackPlugin({
inlineSource: '.(js|css)$',
inject: 'head',
filename: path.join(__dirname, "/dist/index.html"),
template: path.join(__dirname, "/public/index.html"),
chunks: ['common', 'main']
}),
new Jarvis({port: 7003}),
new webpack.HotModuleReplacementPlugin(),
new webpack.DefinePlugin({
_DEVELOPMENT_: true,
})
],
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: { presets: ["es2015", "react", "stage-0"] }
}
},
{
test: /\.jsx$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: { presets: ["es2015", "react", "stage-0"] }
}
},
{
test: /\.scss$/,
use: [
"style-loader", // creates style nodes from JS strings
"css-loader", // translates CSS into CommonJS
"sass-loader" // compiles Sass to CSS, using Node Sass by default
]
},
{
test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
use: ["file-loader"]
},
{
test: /\.svg$/,
use: {
loader: "svg-inline-loader"
}
},
{
test: /\.ts$/,
use: [
{
loader: "ts-loader",
options: {
compilerOptions: {
declaration: false,
target: "es5",
module: "commonjs"
},
transpileOnly: true
}
}
]
}
]
},
resolve: {
alias: {
'react-dom': '#hot-loader/react-dom'
}
},
entry: {
main: [
'babel-polyfill',
'react-hot-loader/patch',
'webpack/hot/only-dev-server',
'webpack-dev-server/client?https://0.0.0.0:7001',
'./src/index.jsx',
],
}
});
dev-server.js
const webpack = require('webpack');
const WebpackDevServer = require('webpack-dev-server');
const config = require('./webpack.dev.config');
new WebpackDevServer(webpack(config), {
publicPath: config.output.publicPath,
headers: {'Access-Control-Allow-Origin': '*'},
hot: true,
https: true,
clientLogLevel: 'error',
overlay: true,
historyApiFallback: true,
disableHostCheck: true,
watchOptions: {
ignored: /\/node_modules\/.*/,
},
stats: {
assets: false,
cached: false,
cachedAssets: false,
children: false,
chunks: false,
chunkModules: false,
chunkOrigins: false,
colors: true,
depth: false,
entrypoints: true,
excludeAssets: /app\/assets/,
hash: false,
maxModules: 15,
modules: false,
performance: true,
reasons: false,
source: false,
timings: true,
version: false,
warnings: true,
},
}).listen(7001, '0.0.0.0', function(err, result) {
console.log(`Serving chunks at path ${config.output.publicPath}`);
});
package.json scripts
"scripts": {
"build": "webpack --config webpack.dev.config.js --progress --profile --colors",
"start-dev": "node dev-server.js",
"build-prod": "webpack --config webpack.prod.js --progress --profile --colors",
"start": "node server.js"
},
If i run
npm run build
The result is a new js bundle and html:
dist/main.js
dist/index.html
however the ideal situation is to run
npm run start-dev
which will start the dev server, this outputs that is has successfully built the bundles, but they never appear in my filesystem so there must be an output config that i have not setup correctly in the dev server?
EDIT
Issue turned out to be as described by the post below.
To access the live bundle reloads i edited the bundle public path from the "production server" back to just the build location, and then accessed the page from the devserver instead of the page being served by the "production server"
output: {
chunkFilename: '[name]-[hash].js',
publicPath: "/build/",
crossOriginLoading: 'anonymous',
path: path.join(__dirname, "/dist"),
},
Webpack dev-server don't write your changes to the disk every time you change your source code. Instead, it watches your files change, process it and serve from memory. Check out here as it explains in detail.

keep folder structure of source files in webpack

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

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