I am writing a React App in Visual Studio 2019 (ASP NET Core 3.1) and having an issue where the App reloads in the browser when I save a new profile picture (to disc).
This is causing issue on the page as its running the UseEffect() before it begins processing the async response with the updated info.
I am able to reproduce this behavior by simply overwriting or deleting the image file from file explorer. And it is important to NOTE that if I attempt to move my images folder outside of SRC folder, I get an error saying this is not allowed.
My initial investigation tells me this has to do with Webpack watching the images folder. But every attempt I have made to prevent it from watching the folder has failed. I have gone over the Webpack documentation many times but nothing seems to change.
I have two config files in my application Webpack.config.js and WebpackDevServer.config.js. It doesn't seem to matter what config I modify it always reloads the App. I have also tried setting the ENV mode to 'development' but again no dice.
Can someone please tell me how to modify the webpack configs to avoid the application from reloading.
If you can provide the above back with the necessary change it would be MUCH appreciated.
src\Images\Users\Profile Pictures - is the path I would like to ignore.
Webpack.config.js
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
// #remove-on-eject-end
'use strict';
const fs = require('fs');
const path = require('path');
const webpack = require('webpack');
const resolve = require('resolve');
const PnpWebpackPlugin = require('pnp-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin');
const TerserPlugin = require('terser-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const safePostCssParser = require('postcss-safe-parser');
const ManifestPlugin = require('webpack-manifest-plugin');
const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
const WorkboxWebpackPlugin = require('workbox-webpack-plugin');
const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent');
const paths = require('./paths');
const modules = require('./modules');
const getClientEnvironment = require('./env');
const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin');
const ForkTsCheckerWebpackPlugin = require('react-dev-utils/ForkTsCheckerWebpackPlugin');
const typescriptFormatter = require('react-dev-utils/typescriptFormatter');
// #remove-on-eject-begin
const getCacheIdentifier = require('react-dev-utils/getCacheIdentifier');
// #remove-on-eject-end
const postcssNormalize = require('postcss-normalize');
const appPackageJson = require(paths.appPackageJson);
// Source maps are resource heavy and can cause out of memory issue for large source files.
const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false';
// Some apps do not need the benefits of saving a web request, so not inlining the chunk
// makes for a smoother build process.
const shouldInlineRuntimeChunk = process.env.INLINE_RUNTIME_CHUNK !== 'false';
const isExtendingEslintConfig = process.env.EXTEND_ESLINT === 'true';
const imageInlineSizeLimit = parseInt(
process.env.IMAGE_INLINE_SIZE_LIMIT || '10000'
);
// Check if TypeScript is setup
const useTypeScript = fs.existsSync(paths.appTsConfig);
// style files regexes
const cssRegex = /\.css$/;
const cssModuleRegex = /\.module\.css$/;
const sassRegex = /\.(scss|sass)$/;
const sassModuleRegex = /\.module\.(scss|sass)$/;
// This is the production and development configuration.
// It is focused on developer experience, fast rebuilds, and a minimal bundle.
module.exports = function (webpackEnv) {
const isEnvDevelopment = webpackEnv === 'development';
const isEnvProduction = webpackEnv === 'production';
// Variable used for enabling profiling in Production
// passed into alias object. Uses a flag if passed into the build command
const isEnvProductionProfile =
isEnvProduction && process.argv.includes('--profile');
// We will provide `paths.publicUrlOrPath` to our app
// as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript.
// Omit trailing slash as %PUBLIC_URL%/xyz looks better than %PUBLIC_URL%xyz.
// Get environment variables to inject into our app.
const env = getClientEnvironment(paths.publicUrlOrPath.slice(0, -1));
// common function to get style loaders
const getStyleLoaders = (cssOptions, preProcessor) => {
const loaders = [
isEnvDevelopment && require.resolve('style-loader'),
isEnvProduction && {
loader: MiniCssExtractPlugin.loader,
// css is located in `static/css`, use '../../' to locate index.html folder
// in production `paths.publicUrlOrPath` can be a relative path
options: paths.publicUrlOrPath.startsWith('.')
? { publicPath: '../../' }
: {},
},
{
.....
WebpackDevServer.config.js
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
// #remove-on-eject-end
'use strict';
const fs = require('fs');
const errorOverlayMiddleware = require('react-dev-utils/errorOverlayMiddleware');
const evalSourceMapMiddleware = require('react-dev-utils/evalSourceMapMiddleware');
const noopServiceWorkerMiddleware = require('react-dev-utils/noopServiceWorkerMiddleware');
const ignoredFiles = require('react-dev-utils/ignoredFiles');
const redirectServedPath = require('react-dev-utils/redirectServedPathMiddleware');
const paths = require('./paths');
const getHttpsConfig = require('./getHttpsConfig');
const host = process.env.HOST || '0.0.0.0';
const sockHost = process.env.WDS_SOCKET_HOST;
const sockPath = process.env.WDS_SOCKET_PATH; // default: '/sockjs-node'
const sockPort = process.env.WDS_SOCKET_PORT;
module.exports = function(proxy, allowedHost) {
return {
// WebpackDevServer 2.4.3 introduced a security fix that prevents remote
// websites from potentially accessing local content through DNS rebinding:
// https://github.com/webpack/webpack-dev-server/issues/887
// https://medium.com/webpack/webpack-dev-server-middleware-security-issues-1489d950874a
// However, it made several existing use cases such as development in cloud
// environment or subdomains in development significantly more complicated:
// https://github.com/facebook/create-react-app/issues/2271
// https://github.com/facebook/create-react-app/issues/2233
// While we're investigating better solutions, for now we will take a
// compromise. Since our WDS configuration only serves files in the `public`
// folder we won't consider accessing them a vulnerability. However, if you
// use the `proxy` feature, it gets more dangerous because it can expose
// remote code execution vulnerabilities in backends like Django and Rails.
// So we will disable the host check normally, but enable it if you have
// specified the `proxy` setting. Finally, we let you override it if you
// really know what you're doing with a special environment variable.
disableHostCheck:
!proxy || process.env.DANGEROUSLY_DISABLE_HOST_CHECK === 'true',
// Enable gzip compression of generated files.
compress: true,
// Silence WebpackDevServer's own logs since they're generally not useful.
// It will still show compile warnings and errors with this setting.
clientLogLevel: 'none',
// By default WebpackDevServer serves physical files from current directory
// in addition to all the virtual build products that it serves from memory.
// This is confusing because those files won’t automatically be available in
// production build folder unless we copy them. However, copying the whole
// project directory is dangerous because we may expose sensitive files.
// Instead, we establish a convention that only files in `public` directory
// get served. Our build script will copy `public` into the `build` folder.
// In `index.html`, you can get URL of `public` folder with %PUBLIC_URL%:
// <link rel="icon" href="%PUBLIC_URL%/favicon.ico">
// In JavaScript code, you can access it with `process.env.PUBLIC_URL`.
// Note that we only recommend to use `public` folder as an escape hatch
// for files like `favicon.ico`, `manifest.json`, and libraries that are
// for some reason broken when imported through webpack. If you just want to
// use an image, put it in `src` and `import` it from JavaScript instead.
contentBase: paths.appPublic,
contentBasePublicPath: paths.publicUrlOrPath,
// By default files from `contentBase` will not trigger a page reload.
watchContentBase: true,
// Enable hot reloading server. It will provide WDS_SOCKET_PATH endpoint
// for the WebpackDevServer client so it can learn when the files were
// updated. The WebpackDevServer client is included as an entry point
// in the webpack development configuration. Note that only changes
// to CSS are currently hot reloaded. JS changes will refresh the browser.
hot: true,
// Use 'ws' instead of 'sockjs-node' on server since we're using native
// websockets in `webpackHotDevClient`.
transportMode: 'ws',
// Prevent a WS client from getting injected as we're already including
// `webpackHotDevClient`.
injectClient: false,
// Enable custom sockjs pathname for websocket connection to hot reloading server.
// Enable custom sockjs hostname, pathname and port for websocket connection
// to hot reloading server.
sockHost,
sockPath,
sockPort,
// It is important to tell WebpackDevServer to use the same "publicPath" path as
// we specified in the webpack config. When homepage is '.', default to serving
// from the root.
// remove last slash so user can land on `/test` instead of `/test/`
publicPath: paths.publicUrlOrPath.slice(0, -1),
// WebpackDevServer is noisy by default so we emit custom message instead
// by listening to the compiler events with `compiler.hooks[...].tap` calls above.
quiet: true,
// Reportedly, this avoids CPU overload on some systems.
// https://github.com/facebook/create-react-app/issues/293
// src/node_modules is not ignored to support absolute imports
// https://github.com/facebook/create-react-app/issues/1065
watchOptions: {
ignored: ignoredFiles(paths.appSrc)
},
...
Thanks Again,
Adam
Related
So currently I have a react application hosted on Amazon S3 and it is served via a Cloudfront CDN however, every new production release I make, the end users have to deep refresh (ctrl+shift+r) the entire page (since the contents of the prev build remain in the browser cache). Is there any I could invalidate both the CDN Cache and the Browser cache only when making a production release. I use GitLab ci btw.
we are using AwsPublish plugin in gulp.
Here's the code for gulp file
const day = 86400;
const farFuture = { 'Cache-Control': `max-age=${day * 365}` };
const future = { 'Cache-Control': `max-age=${day * 7}` };
const noCache = { 'Cache-Control': 'no-cache' };
const gzipTypes = '**/*.{html,css,js,svg,ico,json,txt,wasm,map,mem}';
const cacheBustedTypes = '**/*.{css,js,gif,jpeg,jpg,png,svg,webp,ttf,woff,woff2,wasm}';
const cachedTypes = '**/*.{ico}';
const noCacheTypes = '**/*.{html,json,xml,txt}';
const otherTypes = ['**/*', `!${cacheBustedTypes}`, `!${cachedTypes}`, `!${noCacheTypes}`];
const publisher = $.awspublish.create(awsSettings);
const options = {
force,
};
return gulp
.src(source, { base })
.pipe($.if(gzipTypes, $.awspublish.gzip()))
.pipe($.if(cacheBustedTypes, publisher.publish(farFuture, options)))
.pipe($.if(cachedTypes, publisher.publish(future, options)))
.pipe($.if(noCacheTypes, publisher.publish(noCache, options)))
.pipe($.if(otherTypes, publisher.publish(null, options)))
.pipe($.if(sync, publisher.sync()))
.pipe($.awspublish.reporter());
});
Add index.html in noCacheTypes types. Webpack would generate chunkhash for css and js files and upon changing them the cache would be busted.
We're using github actions along with this gulp script.
I'm using the pre-build-webpack plugin to merge several json files into 1 json array every time I start my app (npm run serve or npm run build), but the problem is that it gets caught in an infinite webpack compile loop in when I start the development server. I managed to find a solution to the problem by using the watch-ignore-webpack-plugin plugin, which initially seemed to have resolved the issue - webpack will now compile everything twice (it seems) and then it's good to go and I can access my local server. But the problem now is that when I visit localhost:8080 there's nothing. The screen's blank and there's nothing being console.log()ed, so I don't know what to do anymore.
If anyone's seen anything like this or know how to fix it, please let me know. If you require any additional info, also let me know.
Versions:
vue: 2.6.10 (as seen in package.json)
vue-cli: 3.11.0 (running vue -V in cmd)
pre-build-webpack: 0.1.0
watch-ignore-webpack-plugin: 1.0.0
webpack-log: 3.0.1
vue.config.js (with everything irrelevant removed):
const WebpackPreBuildPlugin = require('pre-build-webpack');
const WatchIgnorePlugin = require('watch-ignore-webpack-plugin');
module.exports = {
configureWebpack: {
plugins: [
new WebpackPreBuildPlugin(() => {
const fs = require('fs');
const glob = require('glob');
const log = require('webpack-log')({ name: 'ATTENTION!' });
const output = [];
const exclude = [];
glob('./src/components/mods/**/*.json', (err, paths) => {
paths.forEach(path => {
const content = JSON.parse(fs.readFileSync(path, 'utf-8'));
const pathSplit = path.split('/');
const modFolderName = pathSplit[pathSplit.length - 2]
if(!output.filter(val => val.id === content.id)[0]) {
if(exclude.indexOf(modFolderName) === -1) {
output.push(content);
} else {
log.warn(`SKIPPING CONTENTS OF "${modFolderName}"`);
}
} else {
log.error(`MOD WITH ID "${content.id}" ALREADY EXISTS!`);
process.exit(0);
}
});
// If I take out this line, the infinite loop doesn't occur, but then, of
// course, I don't get my merged json file either.
fs.writeFileSync('./src/config/modules/layoutConfig.json', JSON.stringify(output));
});
}),
// Neither of the blow paths work.
new WatchIgnorePlugin([/\layoutConfig.json$/]),
// new WatchIgnorePlugin(['./src/config/modules/layoutConfig.json']),
]
}
};
I am using Parcel middleware with express as explained here: https://parceljs.org/api.html#middleware
When I run this in production I don't want hot-module replacement to be turned on.
How can I set this up so that it works in dev with HMR and in prod without HMR? Essentially I don't know how to use the build mode with this middleware: https://parceljs.org/production.html#%E2%9C%A8-production
Should I only use parcel-bundler if this is in dev and use static config if this is in prod?
Adding sample code for reference:
const Bundler = require('parcel-bundler');
const app = require('express')();
const file = 'index.html'; // Pass an absolute path to the entrypoint here
const options = {}; // See options section of api docs, for the possibilities
// Initialize a new bundler using a file and options
const bundler = new Bundler(file, options);
// Let express use the bundler middleware, this will let Parcel handle every request over your express server
app.use(bundler.middleware());
// Listen on port 8080
app.listen(8080);
You can set options for the bundler as so
const bundlerOptions = { production: process.env.NODE_ENV === 'production' };
const bundler = new Bundler( filePath, bundlerOptions );
This will disable HMR as described in the parcel documentation https://parceljs.org/api.html.
I'm using mirage to mock some data and I'd like to mock an <img> with the appropriate file.
The problem is that I will have to place the image in /public/assets and the images placed there will be deployed later on as well.
Is there a way to avoid this? I couldn't find a recommendation in the ember cli website (https://ember-cli.com/user-guide/#asset-compilation)
I found one addon that could do this (ember-test-assets), but I'd like to avoid installing extra addons as much as possible.
Thanks!
You can exclude files in ember-cli-build.js with some help of Broccoli
const EmberApp = require('ember-cli/lib/broccoli/ember-app');
const Funnel = require('broccoli-funnel');
module.exports = function(defaults) {
let app = new EmberApp(defaults, {
// Add options here
});
// Filter your test files in 'production'
if (EmberApp.env() === 'production') {
return new Funnel(app.toTree(), {
exclude: ['**/test-*'] // e.g. any file prefixxed with 'test-'
});
}
return app.toTree();
};
References:
EmberApp.env(): https://github.com/ember-cli/ember-cli/blob/d97d96aa016fbe8108c2d2744c9823a0ea086b94/lib/broccoli/ember-app.js#L469
broccoli-funnel: https://github.com/broccolijs/broccoli-funnel (see exclude)
I'm uploading a file from a browser <input type="file" name="myfile" id="myfile" using sails. I need to place it in other than the default express location. I'd use the following code in naked Express:
app.use(express.bodyParser({ keepExtensions: true, uploadDir: uploadFolder }))
For sails I wrote code along the lines of this relevant answer
First, I tried SkyTecLabs' answer. policies/configfileupload.js contains
'use strict';
var sailsExpress = require('../../node_modules/sails/node_modules/express'),
path = require('path');
console.log('.. initializing policies/configFileUpload');
module.exports = function configFileUpload (req, res, next) {
var uploadFolder = path.normalize(__dirname + '/../public/uploads');
console.log('.. in policies/configfileupload.js. uploadFolder=', uploadFolder);
console.log('typeofs are=',typeof req, typeof res, typeof next, typeof sailsExpress);
sailsExpress.bodyParser({ keepExtensions: true, uploadDir: uploadFolder });
next();
};
config/policies.js contains
'SchedController' : {
'uploadsubmit': 'configfileupload'
}
Express continues to upload the file to the default directory. Typeof req, res, next, sailsexpress are: object, object, function, function so the signature looks OK. (I tried returning the function configFileUpload just in case, but the controller was never called.)
Then I tried mikemcneil's suggestion. config/express.js
'use strict';
var sailsExpress = require('../node_modules/sails/node_modules/express'),
path = require('path');
module.exports.express = {
customMiddleware: function (app) {
var uploadFolder = path.normalize(__dirname + '/../public/uploads');
console.log('.. in config/express.js. uploadFolder=', uploadFolder);
console.log('typeof sailsExpress=', typeof sailsExpress, 'typeof app=', typeof app);
app.use(sailsExpress.bodyParser({ keepExtensions: true, uploadDir: uploadFolder }));
}
};
and the upload was still placed in the default directory. The typeofs sailsexpress and app are both function.
If the above code is correct for including express middleware in sails, then perhaps this middleware is performed only after express' formidable dependency parses the data and uploads the file.
I don't know in this case of any place in sails where I can place express configuration options such as bodyParser.
Warning: Before you release your app...
If you're expecting lots of file uploads, and especially big ones, you need to reconsider your strategy before deploying into production. You can replace the bodyParser middleware manually by replacing sails.config.express.bodyParser.
The default bodyParser in Express/Connect (and Sails, as of v0.9.x) uses a tmp directory to buffer files (similar to what you'd see in PHP). To get uploaded files somewhere else, you'll need to move them. Check out http://howtonode.org/really-simple-file-uploads for more on how to do that.
There is another option you might check out, depending on how adventurous you are. As I have time, I've been working on an alternative default bodyParser that can be used with Sails or Express. It defers to the underlying library for param/JSON parsing, but uses formidable's raw onPart events to allow streaming uploads without writing the entire file to disk. More on that:
Example repo: https://github.com/mikermcneil/stream-debug
Discussion: https://groups.google.com/d/msg/sailsjs/525fK7pgK8U/bduPudCSLUgJ
Source: https://github.com/mikermcneil/file-parser