Vue cli. How to build with the same hash - docker

i have a problem with hashes in vue cli build.
And now to the details.
I build my app, and in dist folder i see my files with names like
app.dsadas.js, chunk-1-dsadaas.js etc.. all looks good.
But i build my app in docker images, there may be 2 or more, and i need all this images with the same hashes in filenames, but it is not.
This 'webpack-md5-hash' plugin helped me with this problem, but its very old solution, works with warnings.
Help pls find solution for webpack 4.
This is my vue config file:
const path = require('path');
const VuetifyLoaderPlugin = require('vuetify-loader/lib/plugin');
const CompressionWebpackPlugin = require('compression-webpack-plugin');
const productionGzipExtensions = ['js', 'css'];
function resolve(dir) {
return path.resolve(__dirname, dir);
}
module.exports = {
assetsDir: 'static',
runtimeCompiler: true,
lintOnSave: process.env.NODE_ENV !== 'production',
devServer: {
overlay: {
warnings: true,
errors: true,
},
},
configureWebpack: {
performance: {
hints: false,
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
vue$: 'vue/dist/vue.esm.js',
'#': resolve('src'),
utils: resolve('src/utils'),
api: resolve('src/api'),
defaultStates: resolve('src/store/modules/defaultStates'),
router: resolve('src/router'),
store: resolve('src/store'),
config: resolve('src/config'),
helpers: resolve('src/store/modules/helpers'),
constants: resolve('src/constants'),
mixins: resolve('src/mixins'),
},
},
plugins: [
new VuetifyLoaderPlugin(),
new CompressionWebpackPlugin({
filename: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp(`\\.(${productionGzipExtensions.join('|')})$`),
threshold: 10240,
minRatio: 0.8,
}),
],
},
};

Related

Webpack 5 livereload enabled but not working

I'm having trouble with the Live Reload in Webpack 5 not working. The browser console says:
[webpack-dev-server] Live Reloading enabled.
but it does not reload when I change/save a file. There are no errors in the browser console or terminal.
I'm on Windows 10, using an official Alpine Linux Docker image; my browser is Chrome Version 102.0.5005.63 (Official Build) (64-bit). The project is a fairly simple front end web app.
My package.json dev dependencies:
"devDependencies": {
"html-webpack-plugin": "^5.5.0",
"webpack": "^5.72.0",
"webpack-cli": "^4.9.2",
"webpack-dev-server": "^4.9.0",
"webpack-webmanifest-loader": "^2.0.2" }
My webpack.config.js file:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: "./src/index.js",
mode: "development",
devtool: "inline-source-map",
target: "web",
devServer: {
static: {
directory: path.join(__dirname, "src"),
},
compress: true,
hot: false,
port: 3000,
liveReload: true,
watchFiles: "./src/*",
},
plugins: [
new HtmlWebpackPlugin({
title: "Title",
template: "src/index.html",
}),
],
output: {
filename: "[name].bundle.js",
path: path.resolve(__dirname, "dist"),
clean: true,
},
module: {
rules: [
{
test: /\.(png|svg|webp|jpg|jpeg)$/i,
type: "asset/resource",
},
{
test: /\.(json|txt|mp3)$/i,
type: "asset/resource",
},
{
test: /\.webmanifest$/i,
use: "webpack-webmanifest-loader",
type: "asset/resource",
},
],
},
};
When starting the dev server I use the following commands:
npx webpack serve --static assets
My file/folder structure:
New to Webpack in general. Please help!
After sifting through lots of google searches, I finally found a solution in the official webpack documentation: watchOptions.
If watching does not work for you, try out this option. This may help issues with NFS and machines in VirtualBox, WSL, Containers, or Docker. In those cases, use a polling interval and ignore large folders like /node_modules/ to keep CPU usage minimal.
Sooo.... still not sure why it doesn't work with the regular watch option, but polling does work at this time in a docker container.
Here's my webpack.config.js file:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: "./src/index.js",
mode: "development",
devtool: "inline-source-map",
target: "web",
devServer: {
static: ["assets"],
compress: true,
hot: false,
port: 3000,
},
watchOptions: {
ignored: "/node_modules/",
poll: 1000, // Check for changes every second
},
output: {
filename: "[name].bundle.js",
path: path.resolve(__dirname, "dist"),
clean: true,
},
plugins: [
new HtmlWebpackPlugin({
title: "Title",
template: "src/index.html",
}),
],
module: {
rules: [
{
test: /\.(png|svg|webp|jpg|jpeg|json|txt|mp3)$/i,
type: "asset/resource",
},
{
test: /\.webmanifest$/i,
use: "webpack-webmanifest-loader",
type: "asset/resource",
},
],
},
};
I use the following command to start it:
npx webpack serve

How to you modify the precache manifest file generated by Workbox? Need urls to have preceding '/'

In the generated precache-manifest.*.js file the URLs all reference relative paths when I need absolute since my app will have some sub-directories as well.
Example of generated file:
self.__precacheManifest = (self.__precacheManifest || []).concat([
{
"revision": "1d94d834b7044ec6d4e9",
"url": "js/app.js"
},
{
"revision": "632f09e6ed606bbed1f1",
"url": "css/app.css"
},
...
}
When I need it to look like this:
self.__precacheManifest = (self.__precacheManifest || []).concat([
{
"revision": "1d94d834b7044ec6d4e9",
"url": "/js/app.js"
},
{
"revision": "632f09e6ed606bbed1f1",
"url": "/css/app.css"
},
...
}
I'm using webpack 4.41.0 and workbox-webpack-plugin 4.3.1
Any help would be greatly appreciated! I can add more detail if needed as well.
Here's my webpack config:
let config = {
entry,
stats: {
hash: false,
version: false,
timings: false,
children: false,
errorDetails: false,
entrypoints: false,
performance: inProduction,
chunks: false,
modules: false,
reasons: false,
source: false,
publicPath: false,
builtAt: false
},
performance: { hints: false },
// Valid options: "production" | "development" | "none"
mode: inProduction ? 'production' : 'development',
plugins: [
new CopyPlugin(copyConfig),
new webpack.ProvidePlugin(providers), // Providers, e.g. jQuery
new WebpackNotifierPlugin({ title: 'Webpack' }), // OS notification
new VueLoaderPlugin(), // Vue-loader
new CleanWebpackPlugin(pathsToClean, cleanOptions), // Clean up pre-compile time
new ManifestPlugin(manifestOptions), // Manifest file
new FriendlyErrorsWebpackPlugin({ clearConsole: true }), // Prettify console
new MiniCssExtractPlugin(cssOptions), // Extract CSS files
new WebpackMd5Hash(), // use md5 for hashing
{
/* Laravel Spark RTL support */
apply: (compiler) => {
compiler.hooks.afterEmit.tap('AfterEmitPlugin', (compilation) => {
exec('node_modules/rtlcss/bin/rtlcss.js public/css/app-rtl.css ./public/css/app-rtl.css', (err, stdout, stderr) => {
if (stdout) process.stdout.write(stdout);
if (stderr) process.stderr.write(stderr);
});
});
}
}
],
module: {
rules: [
{
test: /\.vue$/,
use: ['vue-loader']
},
{
test: /\.s?css$/,
use: [
'style-loader',
{
loader: MiniCssExtractPlugin.loader,
options: { hmr: isHot } // set HMR if flagged
},
'css-loader',
'postcss-loader',
'sass-loader'
]
}
]
},
resolve: {
extensions: ['.js', '.json', '.vue'],
modules: ['node_modules'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'~': path.join(__dirname, 'resources/assets/js'),
jquery: "jquery/src/jquery",
}
},
output: {
filename: 'js/[name].js',
// chunkFilename: inProduction ? 'js/[name].[chunkhash].js' : 'js/[name].js',
path: publicPath,
},
optimization: {
...optimization,
concatenateModules: false,
providedExports: false,
usedExports: false,
},
devtool: inDevelopment ? 'eval-source-map' : false,
devServer: {
headers: {
'Access-Control-Allow-Origin': '*'
},
port: port,
contentBase: publicPath,
historyApiFallback: true,
noInfo: false,
compress: true,
quiet: true,
hot: isHot,
}
}
And my GenerateSW:
new GenerateSW({
// The cache ID
cacheId: 'pwa',
// The path and filename of the service worker file that will be created by the build process, relative to the webpack output directory.
swDest: path.join(publicPath, 'sw.js'),
clientsClaim: true,
skipWaiting: true,
// Files to exclude from the precache
exclude: [/\.(?:png|jpg|jpeg|svg)$/, /\.map$/, /manifest\.json$/, /service-worker\.js$/, /sw\.js$/],
// Default fall-back url
navigateFallback: '/',
// An optional array of regular expressions that restricts which URLs the configured navigateFallback behavior applies to.
// This is useful if only a subset of your site's URLs should be treated as being part of a Single Page App.
navigateFallbackWhitelist: [
/^\/media\//,
/^\/settings\//,
],
// Runtime cache
runtimeCaching: [
{
urlPattern: new RegExp(`${process.env.APP_URL}`),
handler: 'NetworkFirst',
options: {
cacheName: `${process.env.APP_NAME}-${process.env.APP_ENV}`
}
},
{
urlPattern: new RegExp('https://fonts.(googleapis|gstatic).com'),
handler: 'CacheFirst',
options: {
cacheName: 'google-fonts'
}
}
]
}
)
And a couple of defined common variables:
...
// Production flag
const inProduction = process.env.NODE_ENV === 'production'
const inDevelopment = process.env.NODE_ENV === 'development'
// HMR
const isHot = process.argv.includes('--hot')
// Public/webroot path
const publicPath = path.resolve(__dirname, 'public')
// Primary webpack entry point(s)
const entry = {
/*
* JS entry point/Vue base component
* Make sure to import your css files here, e.g. `import '../sass/app.scss'`
*/
app: path.resolve(__dirname, 'resources/assets/js/app.js'),
}
...
For anyone visiting this question, you can use the webpack output.publicPath setting to add a prefix to your manifest URLS like so:
plugins: [
new InjectManifest({}) // Left here just for reference
],
output: {
publicPath: '/' // You can add your prefix here
}

React on Rails with server side rendering

I created a site using React on Rails. It works perfectly fine, but I have not noticed that server side rendering is turned off, and I need it for SEO so I decided to turn it on. The thing is that now I get an error like this:
ERROR in SERVER PRERENDERING
Encountered error: "ReferenceError: window is not defined"
My webpack.config.js looks like this:
/* eslint comma-dangle: ["error",
{"functions": "never", "arrays": "only-multiline", "objects":
"only-multiline"} ] */
const webpack = require('webpack');
const path = require('path');
const devBuild = process.env.NODE_ENV !== 'production';
const nodeEnv = devBuild ? 'development' : 'production';
const bundles = [
'./app/bundles/Home/startup/registration'
]
const config = {
entry: [
'es5-shim/es5-shim',
'es5-shim/es5-sham',
'babel-polyfill',
...bundles
],
output: {
filename: 'webpack-bundle.js',
path: '../app/assets/webpack',
},
resolve: {
extensions: ['', '.js', '.jsx'],
alias: {
react: path.resolve('./node_modules/react'),
'react-dom': path.resolve('./node_modules/react-dom'),
},
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(nodeEnv),
},
}),
],
module: {
loaders: [
{
test: require.resolve('react'),
loader: 'imports?shim=es5-shim/es5-shim&sham=es5-shim/es5-sham',
},
{
test: /\.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/,
},
],
},
};
module.exports = config;
if (devBuild) {
console.log('Webpack dev build for Rails'); // eslint-disable-line no-console
module.exports.devtool = 'eval-source-map';
} else {
config.plugins.push(
new webpack.optimize.DedupePlugin()
);
console.log('Webpack production build for Rails'); // eslint-disable-line no-console
}
What should I do to fix it? I read through one of the realted issues on react_on_rails github but I still do not know.

Accessing webpack assets from rails app

I'm using webpack with React on Rails and have some react components that need to reference images.
The problem I'm having is trying to get Rails to access the images. Rails has its images served from its usual app/assets/images directory which is accessed via the url /assets
If however I have a react component and an image in an image directory:
component.js
images/image.jpg
+--component.js
+--images/image.jpg
If I try to reference the image by its relative path within component.js eg When I load the page in rails the page tries to access the url http://localhost:3000/home/images/image.jpg and not the url that rails expects the assets to be http://localhost:3000/assets/images/image.jpg
Does anyone know how to correct this?
This is my webpack.config
const webpack = require('webpack')
const path = require('path')
const devBuild = process.env.NODE_ENV !== 'production'
const nodeEnv = devBuild ? 'development' : 'production'
const config = {
entry: [
'whatwg-fetch',
'es5-shim/es5-shim',
'es5-shim/es5-sham',
'babel-polyfill',
'./app/bundles/index.js'
],
output: {
filename: 'webpack-bundle.js',
path: '../app/assets/webpack'
},
resolve: {
extensions: ['', '.js', '.jsx'],
alias: {
react: path.resolve('./node_modules/react'),
'react-dom': path.resolve('./node_modules/react-dom')
}
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(nodeEnv)
}
})
],
module: {
loaders: [
{
test: require.resolve('react'),
loader: 'imports?shim=es5-shim/es5-shim&sham=es5-shim/es5-sham'
},
{
test: /\.(jpe?g|png|gif|svg|ico)$/, loader: 'file-loader'
},
{
test: /\.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/
}
]
}
}
module.exports = config
if (devBuild) {
console.log('Webpack dev build for Rails') // eslint-disable-line no-console
module.exports.devtool = 'eval-source-map'
} else {
config.plugins.push(
new webpack.optimize.DedupePlugin()
)
console.log('Webpack production build for Rails') // eslint-disable-line no-console
}

Rails + React + Webpack loading an image

I'm using rails + webpack to compile a bundle.js file into the rails asset pipeline. I placed an image inside /app/assets/images called "main.png". How can I access this image inside a React component that's being bundled?
I'm using shakacode's react on rails gem. https://github.com/shakacode/react_on_rails
I then tried using webpack to process the image which it did successfully and placed the image next to the bundle.js file. I still get a 404 on the image.
I know I'm close, just have the publicPath wrong for the rails asset. This current setup gives a localhost:3000/webpack/main.png which isn't working with rails.
This is my webpack file:
const webpack = require('webpack');
const path = require('path');
const devBuild = process.env.NODE_ENV !== 'production';
const nodeEnv = devBuild ? 'development' : 'production';
config = {
entry: [
'es5-shim/es5-shim',
'es5-shim/es5-sham',
'babel-polyfill',
'./app/Register.js',
],
output: {
filename: 'webpack-bundle.js',
path: '../app/assets/webpack',
publicPath: '/webpack/'
},
resolve: {
extensions: ['', '.js', '.jsx'],
alias: {
react: path.resolve('./node_modules/react'),
'react-dom': path.resolve('./node_modules/react-dom'),
},
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(nodeEnv),
},
}),
],
module: {
loaders: [
{
test: require.resolve('react'),
loader: 'imports?shim=es5-shim/es5-shim&sham=es5-shim/es5-sham',
},
{
test: /\.jsx?$/, loader: 'babel-loader',
exclude: /node_modules/,
},
{
test: /\.(png|svg)$/i,
loaders: [
'file?hash=sha512&digest=hex&name=[hash].[ext]',
'image-webpack?bypassOnDebug&interlaced=false'
]
}
],
},
};
module.exports = config;
if (devBuild) {
console.log('Webpack dev build for Rails'); // eslint-disable-line no-console
module.exports.devtool = 'eval-source-map';
} else {
config.plugins.push(
new webpack.optimize.DedupePlugin()
);
console.log('Webpack production build for Rails'); // eslint-disable-line no-console
}
After defining a loader properly, you can load your image with a require function, for example! For example, add near your imports:
const myImg = require('./assets/methods.png');
Then, in your component's render method:
<img src={myImg} />
That should work...

Resources