Why express.js can not find static files? - node.js

I created simple express.js server
Server config:
const app = express();
const config = require('./webpack.config.js');
const compiler = webpack(config);
const SERVER_PORT = 3000;
if (process.env.NODE_ENV === "development") {
app.use(
webpackDevMiddleware(compiler, {
publicPath: config.output.publicPath,
})
);
app.use(webpackHotMiddleware(compiler));
}
app.use(express.static("build"));
app.get("/", (req, res) => {
res.sendFile(__dirname + '/build/index.html', { root: __dirname })
});
app.listen(SERVER_PORT, (error) => {
if (error) {
console.error(error)
} else {
console.info("==> 🌎 Listening on port %s. Open up http://localhost:%s/ in your browser.", SERVER_PORT, SERVER_PORT)
}
});
I build project with webpack. here is webpack config:
const BUILD_DIR = path.resolve(__dirname, './build');
const ASSETS_PATH = path.resolve(__dirname, './src/js');
const STATIC_PATH = path.resolve(__dirname, './public')
var webpack_config = {
mode: ( process.env.NODE_ENV === "production" ) ? "production" : "development",
context: __dirname,
entry: {
main: [
"react",
"react-dom",
"react-router"
],
react_app: [
path.join(ASSETS_PATH, "/index.tsx"),
"webpack-hot-middleware/client?path=/__webpack_hmr&reload=true"
]
},
output: {
path: BUILD_DIR,
filename: 'js/[name].min.js',
publicPath: '/build',
hotUpdateChunkFilename: '.hot/hot-update.js',
hotUpdateMainFilename: '.hot/hot-update.json',
},
resolve: {
extensions: [' ', '.web.js', '.ts', '.tsx', '.js', '.jsx', 'css'],
},
devtool: ("production" === process.env.NODE_ENV) ? "source-map" : "eval-source-map",
module: {
rules: [
{
test: /\.(jsx|js)$/,
use: ['babel-loader?compact=true&comments=true&minified=true', 'eslint-loader'],
exclude: /node_modules/
},
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: '/node_modules/'
},
{
test: /\.(ttf|woff|woff2)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
use: {
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: '/css/fonts/'
}
}
},
{
test: /\.(eot|svg|png|jpg|gif|ico)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
use: {
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: '/css/media/'
}
}
},
{
test: /\.jpe?g$|\.ico$|\.gif$|\.png$/,
exclude: /node_modules/,
use: {
loader: 'file-loader',
options: {
limit: 1024 * 10,
name: '[name].[ext]',
outputPath: 'images/'
}
}
},
{
test: /\.json$/,
loader: "json-loader"
},
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
}
}
, 'css-loader'],
},
]
},
plugins: [
new webpack.DefinePlugin({
"process.env": {
NODE_ENV: JSON.stringify(process.env.NODE_ENV)
}
}),
new webpack.HotModuleReplacementPlugin(),
new HtmlWebpackPlugin({
title: ' Appointment-APP | Stefanini EMEA ',
template: './public/index.html',
filename: path.join(BUILD_DIR, '/index.html'),
chunks: ['main', 'react_app']
}),
new CopyWebpackPlugin({
patterns: [
{
from: path.join(STATIC_PATH, '/images'),
to: path.join(BUILD_DIR, '/images'),
toType: 'dir'
},
]
}),
new MiniCssExtractPlugin({
filename: 'css/[name].css',
chunkFilename: '[id].css',
}),
],
};
Here I have 2 mods- production and delete. In delete mode it works nice, but when I launch server and try to enter http://localhost:3000/ I get errors like:
Refused to apply style from 'http://localhost:3000/build/css/react_app.css' because its MIME type ('text/html') is not a supported stylesheet MIME type, and strict MIME checking is enabled.
localhost/:9 GET http://localhost:3000/build/js/main.min.js net::ERR_ABORTED 404 (Not Found)
So, I specified static folder path - app.use(express.static("build"));, but no result. It seems, that express cannot find files in "buid" folder

You have to code like this
app.use('/', express.static(path.join(__dirname, 'build')))
then check.

may be this will be useful for somebody. to solve this issue I used express documentation and Jay Suchak variant. Code
app.use('/build', express.static(path.join(__dirname, 'build')));
worked for me

Related

Invalid configuration object. Webpack has been initialized using a configuration object that does not match the API schema

im installing a laravel x vue template (https://pixinvent.com/demo/vuexy-vuejs-admin-dashboard-template/landing/) and while i run npm dev i get this error:
Invalid configuration object. Webpack has been initialized using a configuration object that does not match the API schema.- configuration.module.rules[12].rules should be an array:
My webpack.mix.js looks like this:
const mix = require('laravel-mix')
const path = require('path');
mix
.js('resources/js/app.js', 'public/js')
.webpackConfig({
resolve: {
alias: {
'#resources': path.resolve(__dirname, 'resources/'),
'#': path.resolve(__dirname, 'resources/js/src/'),
'#themeConfig': path.resolve(__dirname, 'resources/js/themeConfig.js'),
'#core': path.resolve(__dirname, 'resources/js/src/#core'),
'#validations': path.resolve(__dirname, 'resources/js/src/#core/utils/validations/validations.js'),
'#axios': path.resolve(__dirname, 'resources/js/src/libs/axios'),
},
},
module: {
rules: [
{
test: /\.s[ac]ss$/i,
rules: [
{
loader: 'sass-loader',
options: {
sassOptions: {
includePaths: ['node_modules', 'resources/assets'],
},
},
},
],
},
{
enforce: "pre",
test: /(\.(png|jpe?g|gif|webp)$|^((?!font).)*\.svg$)/,
rules: {
loader: 'file-loader',
options: {
name: 'images/[path][name].[ext]',
context: '../vuexy-vuejs-bootstrap-vue-template/src/assets/images',
// context: 'frontend/src/assets/images'
},
},
},
],
},
})
.sass('resources/scss/core.scss', 'public/css')
.options({
postCss: [require('autoprefixer'), require('postcss-rtl')],
})
mix.copy('resources/css/loader.css', 'public/css')
if (mix.inProduction()) {
mix.version()
mix.webpackConfig({
output: {
publicPath: '/demo/vuexy-vuejs-laravel-admin-template/demo-1/',
chunkFilename: 'js/chunks/[name].[chunkhash].js'
}
})
mix.setResourceRoot('/demo/vuexy-vuejs-laravel-admin-template/demo-1/')
}
*/
mix.webpackConfig({
output: {
chunkFilename: 'js/chunks/[name].[chunkhash].js',
},
})
mix.browserSync('http://127.0.0.1:8000/')

Much older version of my Website shows when rebuilding Production Bundle with Webpack

I've noticed that when I rebuild my production bundle of my node.js app using webpack, the site in the browser reverts to a way older version (300+ git commits later). I use pm2 to run my website on my VPS.
How to keep the oldest version live until the new production build is done?
This is my webpack setup:
const { resolve } = require('path');
const webpack = require('webpack');
const CompressionPlugin = require('compression-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const cssOutputLocation = process.env.NODE_ENV === 'production' ?
'public/stylesheets/style-prod.css' :
'stylesheets/style.css';
const jsProdOutput = {
filename: 'public/javascripts/build-prod.js',
path: resolve(__dirname),
publicPath: '/',
};
const jsDevOutput = {
filename: 'javascripts/build.js',
path: '/',
publicPath: '/',
};
const jsOutputLocation = process.env.NODE_ENV === 'production' ? jsProdOutput : jsDevOutput;
module.exports = {
context: resolve(__dirname, 'src'),
entry: [
'./index.jsx',
],
output: jsOutputLocation,
resolve: {
extensions: ['.js', '.jsx'],
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /(node_modules|bower_components|public\/)/,
loader: 'babel-loader',
query: {
presets: ['es2015', 'es2017'],
},
},
{
test: /\.js?$/,
exclude: /(node_modules|bower_components|public\/)/,
loader: 'babel-loader',
query: {
presets: ['es2015', 'es2017'],
},
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: 'css-loader',
}),
},
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
use: [
{
loader: 'css-loader',
},
{
loader: 'sass-loader',
},
],
fallback: 'style-loader',
}),
},
],
},
plugins: [
new webpack.NamedModulesPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
new ExtractTextPlugin(cssOutputLocation),
new BundleAnalyzerPlugin(),
new webpack.ContextReplacementPlugin(/^\.\/locale$/, (context) => {
if (!/\/moment\//.test(context.context)) { return; }
// context needs to be modified in place
Object.assign(context, {
// include only CJK
regExp: /^\.\/(nl|en-gb)/,
// point to the locale data folder relative to moment's src/lib/locale
request: '../../locale',
});
}),
],
};
if (process.env.NODE_ENV === 'production') {
module.exports.plugins.push(new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false,
screw_ie8: true,
conditionals: true,
unused: true,
comparisons: true,
sequences: true,
dead_code: true,
evaluate: true,
if_return: true,
join_vars: true,
},
output: {
comments: false,
},
}));
module.exports.plugins.push(new webpack.HashedModuleIdsPlugin());
module.exports.plugins.push(new webpack.optimize.ModuleConcatenationPlugin());
module.exports.plugins.push(
new webpack.DefinePlugin(
{ 'process.env.NODE_ENV': JSON.stringify('production') },
),
);
module.exports.plugins.push(
new CompressionPlugin({
asset: '[path].gz[query]',
algorithm: 'gzip',
test: /\.js$|\.css$|\.html$|\.eot?.+$|\.ttf?.+$|\.woff?.+$|\.svg?.+$/,
threshold: 10240,
minRatio: 0.8,
}),
);
}
if (process.env.NODE_ENV !== 'production') {
module.exports.entry.unshift(
'react-hot-loader/patch',
'react-hot-loader/babel',
'webpack-hot-middleware/client',
);
module.exports.plugins.unshift(new webpack.HotModuleReplacementPlugin());
}
You can use the hash placeholder in the filename prop of your output config.
const jsProdOutput = {
filename: 'public/javascripts/build-prod-[hash].js',
path: resolve(__dirname),
publicPath: '/',
};
With this your generated files will be unique on every build and will not be overridden.

asset_url_for() returns None in flask cookie cutter (flask-webpack)

Im new to webpack. Im using flask-cookie-cutter which in turn uses Flask-Webpack
Im having issues in that App wont find my images in development.
Images are in assets/img folder
Ive tried using {{ asset_url_for('img/img_name.png') }} and various variations of it - and it just returns none.
Ive tried the usual flask way of {{ url_for('static', filename='img/img_name.png') }}
But I cant seem to access them.
const path = require('path');
const webpack = require('webpack');
/*
* Webpack Plugins
*/
const ManifestRevisionPlugin = require('manifest-revision-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// take debug mode from the environment
const debug = (process.env.NODE_ENV !== 'production');
// Development asset host (webpack dev server)
const publicHost = debug ? 'http://0.0.0.0:2992' : '';
const rootAssetPath = path.join(__dirname, 'assets');
module.exports = {
// configuration
context: __dirname,
entry: {
main_js: './assets/js/main',
main_css: [
path.join(__dirname, 'node_modules', 'materialize-css', 'dist', 'css', 'materialize.css'),
path.join(__dirname, 'assets', 'css', 'style.css'),
],
},
output: {
path: path.join(__dirname, 'dsi_website', 'static', 'build'),
publicPath: `${publicHost}/static/build/`,
filename: '[name].[hash].js',
chunkFilename: '[id].[hash].js',
},
resolve: {
extensions: ['.js', '.jsx', '.css'],
},
devtool: 'source-map',
devServer: {
headers: { 'Access-Control-Allow-Origin': '*' },
},
module: {
rules: [
{
test: /\.less$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: debug,
},
},
'css-loader!less-loader',
],
},
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: debug,
},
},
'css-loader',
],
},
{
test: /\.html$/,
loader: 'raw-loader'
},
{
test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'application/font-woff'
}
},
{
test: /\.(ttf|eot|svg|png|jpe?g|gif|ico)(\?.*)?$/i,
loader: `file-loader?context=${rootAssetPath}&name=[path][name].[hash].[ext]`
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['env'],
cacheDirectory: true
}
},
],
},
plugins: [
new MiniCssExtractPlugin({ filename: '[name].[hash].css', }),
new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery' }),
new ManifestRevisionPlugin(path.join(__dirname, 'dsi_website', 'webpack', 'manifest.json'), {
rootAssetPath,
ignorePaths: ['/js', '/css'],
}),
].concat(debug ? [] : [
// production webpack plugins go here
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('production'),
}
}),
]),
};
I was the same problem with flask-cookie-cutter and solve it by update/upgrade npm and add extensionsRegex: /\.(jpe?g|png|gif|svg)$/i at down file: webpack.config.js like this:
ManifestRevisionPlugin(path.join(__dirname, '<your app>', 'webpack', 'manifest.json'), {
rootAssetPath,
ignorePaths: ['/js', '/css'],
extensionsRegex: /\.(jpe?g|png|gif|svg)$/i
}),
source solution. Proper call to show image in temaplate:
{{ asset_url_for('img/img_name.png') }}
after that i check startup screen and i see that all my images load properly
[WEBPACK] _/assets/img/image_name.20aed528d50316c91ffedb5ba47b8c74.jpg 18.9 KiB [emitted]

configure webpack to load .vue files in node_modules

I would like to require .vue files from within my node_modules folder but it seems that webpack and | or the .vue loader doesn't transform this files.
This is my configuration right now:
const path = require('path')
const webpack = require('webpack')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')
const isProd = process.env.NODE_ENV === 'production'
module.exports = {
devtool: isProd
? false
: '#cheap-module-source-map',
output: {
path: path.resolve(__dirname, '../dist'),
publicPath: '/dist/',
filename: '[name].[chunkhash].js'
},
resolve: {
alias: {
'public': path.resolve(__dirname, '../public')
}
},
module: {
noParse: /es6-promise\.js$/, // avoid webpack shimming process
rules: [
{
test: /\.pug$/,
loader: 'pug-plain-loader'
},
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
compilerOptions: {
preserveWhitespace: false
}
}
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'url-loader',
options: {
limit: 10000,
name: '[name].[ext]?[hash]'
}
},
{
test: /\.styl(us)?$/,
use: isProd
? ExtractTextPlugin.extract({
use: [
{
loader: 'css-loader',
options: { minimize: true }
},
'stylus-loader'
],
fallback: 'vue-style-loader'
})
: ['vue-style-loader', 'css-loader', 'stylus-loader']
},
]
},
performance: {
maxEntrypointSize: 300000,
hints: isProd ? 'warning' : false
},
plugins: isProd
? [
new VueLoaderPlugin(),
new webpack.optimize.UglifyJsPlugin({
compress: { warnings: false, drop_console:true }
}),
new webpack.optimize.ModuleConcatenationPlugin(),
new ExtractTextPlugin({
filename: 'common.[chunkhash].css'
})
]
: [
new VueLoaderPlugin(),
new FriendlyErrorsPlugin()
]
}
I tried to set
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules\/(?!(my_components_folder)\/).*/
}
but without success.
I'm always getting the error:
(function (exports, require, module, __filename, __dirname) { <template lang="pug">
^
SyntaxError: Unexpected token <
How can I configure webpack to also transform files from within the node_modules folder?
I'm using webpack#3.8.1

Webpack bundled express app fails to lookup view

I run npm run start and server is running fine. When I attempt to view client at localhost, server returns error:
GET / 500 62.700 ms - 2028
Error: Failed to lookup view "error" in views directory "/views"
The application runs fine when just using source files. This error occurs when running application from webpack bundle.
What are the differences between source and bundled files that would make this error occur?
npm:3.8.2
node: 4.2.6
express: 4.13.1
webpack: 1.12.13
babel-loader: 6.2.4
webpack.config.js
var webpack = require('webpack');
var path = require('path');
var nodeModules = {};
fs.readdirSync('node_modules')
.filter(function(x) {
return ['.bin'].indexOf(x) === -1;
})
.forEach(function(mod) {
nodeModules[mod] = 'commonjs ' + mod;
});
module.exports = [
{
entry: {
'app_bundle': './server.js'
},
target: 'node',
query: {
cacheDirectory: true,
presets: ['es2015']
},
module: {
loaders: [
{
test: /\.js$/,
loader: 'babel',
exclude: /node_modules/
}
]
},
resolve: {
extensions: ['', '.js']
},
output: {
path: './',
filename: '[name].js'
},
externals: nodeModules
},
{
entry: [
'./src/index.jsx'
],
target: 'web',
query: {
cacheDirectory: true,
presets: ['es2015']
},
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel'
},
{
test: /\.css$/,
loader: 'style!css!autoprefixer'
},
{ test: /\.(woff|woff2)$/, loader: "url-loader?limit=10000&mimetype=application/font-woff" },
{ test: /\.ttf$/, loader: "file-loader" },
{ test: /\.eot$/, loader: "file-loader" },
{ test: /\.svg$/, loader: "file-loader" }
]
},
resolve: {
alias: {
'react': path.join(__dirname, 'node_modules', 'react')
},
extensions: ['', '.js', '.jsx']
},
output: {
path: __dirname + '/public',
publicPath: '/',
filename: 'webpack_bundle.js'
}
}
];
The error trace tells me that the error is being handled by the production error handler in my app.js file:
// production error handler
app.use(function(err, req, res, next) {
console.log(err);
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
I console.log the error with the following output:
{ [Error: Failed to lookup view "error" in views directory "/views"]
view:
View {
defaultEngine: 'ejs',
ext: '.ejs',
name: 'error',
root: '/views',
engine: [Function],
path: undefined } }
View engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
I'm not sure how to start debugging...
I believe the answer lies in how webpack handles the special __dirname global variable. Webpack's default behavior is to replace __dirname with the "mock" value /. This can be seen in the error you get from express where it's looking for a file at the root of /views, not ./views.
The solution is to add the following section to your webpack configuration:
node: {
__dirname: true
}
Here's the docs which explain this behavior:
https://webpack.github.io/docs/configuration.html#node

Resources