How to output single build.js file for vue production build - vue.js

I'm using vue-cli 2.9.6, and created a vue project using vue init webpack <project name>.
When I call vue run build, it is creating a number of different js files (and names change each time...):
vendor.20d54e752692d648b42a.js
vendor.20d54e752692d648b42a.js.map
app.ed70f310595763347909.js
app.ed70f310595763347909.js.map
manifest.2ae2e69a05c33dfc65f8.js
manifest.2ae2e69a05c33dfc65f8.js.map
And also css files like this:
app.a670fcd1e9a699133143a2b144475068.css
app.a670fcd1e9a699133143a2b144475068.css.map
I would like the output to simply be 2 files:
build.js { for all js }
styles.css { for all css }
How can I achieve this?

for preventing creation of vendor.js and manifest.js just remove following code from webpack.prod.conf.js
// split vendor js into its own file
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks (module) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '../node_modules')
) === 0
)
}
}),
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity
}),
To prevent sourceMaps set in config/index.js the variable productionSourceMap from true to false
Changing name of app.js to build.js can be obtained modifying the entry and outputproperties in webpack.base.conf.js this way:
entry: {
build: './src/main.js'
},
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].js'),
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
},
Update name of the css output file updating options of ExtractTextPluginin webpack.prod.conf.js to filename: utils.assetsPath('css/styles.css'),

// vue.config.js
module.exports = {
chainWebpack: config => {
if(config.plugins.has('extract-css')) {
const extractCSSPlugin = config.plugin('extract-css')
extractCSSPlugin && extractCSSPlugin.tap(() => [{
filename: 'styles.css',
chunkFilename: 'styles.css'
}])
}
},
configureWebpack: {
output: {
filename: 'build.js',
chunkFilename: 'build.js'
}
}
}
or
module.exports = {
configureWebpack: {
optimization: {
splitChunks: false
}
},
filenameHashing: false
}

Related

Avoid browser caching after deploy a Vuejs app

My Vuejs App did not update after deployment for production, every time require "Empty cache and hard reload" to get the updates, I tried a lot of solutions to apply versioning to generated files after build but none of them worked for me, I need a solution to apply new hash for all files after every single build, not just the updated ones.
My vue.config.js file content:
const path = require("path");
module.exports = {
publicPath: process.env.NODE_ENV === "production" ? "/" : "/",
runtimeCompiler: true,
configureWebpack: {
resolve: {
alias: {
// If using the runtime only build
// vue$: "vue/dist/vue.runtime.esm.js" // 'vue/dist/vue.runtime.common.js' for webpack 1
// Or if using full build of Vue (runtime + compiler)
vue$: 'vue/dist/vue.esm.js', // 'vue/dist/vue.common.js' for webpack 1
'#': path.resolve('src'),
src: path.resolve('src'),
assets: path.resolve('src/assets'),
components: path.resolve('src/components'),
services: path.resolve('src/services'),
}
},
output: {
filename: '[name].[hash].js',
},
},
chainWebpack: config => {
config.module
.rule("eslint")
.use("eslint-loader")
.tap(options => {
options.configFile = path.resolve(__dirname, ".eslintrc.js");
return options;
});
},
};
Thanks in advance.
Welcome to the Vue JS cache nightmare. Did you try changing the version value in your package.json? I use to increment the value on each release as per x.y.z semantinc versioning. Maybe doing something like this:
{
"name": "My app",
"version": "1.0.15",
"private": true,
...
}

Serving a modified asset-manifest.json in CRA using CRACO doesn't work

I have just created a new CRA app. In our organization we have a micro frontend framework which has certain requirements when it comes to the the asset file of each micro frontend app. CRA will by default, create a asset-manifest.json file.
https://github.com/facebook/create-react-app/blob/main/packages/react-scripts/config/webpack.config.js#L656
Now I need to change this file to assets.json and make some structural changes as well. To achieve this I use CRACO and add the WebpackManifestPlugin.
const ManifestPlugin = require('webpack-manifest-plugin');
module.exports = {
webpack: {
plugins: {
// tried removing CRA definition for ManifestPlugin.
// It worked, but had no impact on my problem
// remove: ['ManifestPlugin'],
add: [
new ManifestPlugin({
fileName: 'assets.json',
generate: (seed, files, entrypoints) => {
const js = [],
css = [];
files.forEach((file) => {
if (file.path.endsWith('.js') && file.isInitial) {
js.push({ value: file.path, type: 'entry' });
}
if (file.path.endsWith('.css') && file.isInitial) {
css.push({ value: file.path, type: 'entry' });
}
});
return { js, css };
},
})
]
}
}
};
Whenever I build the application, my new assets.json file is generated as expected.
However, I can't get CRA, or webpack-dev-server I assume, to serve this file while I run my CRA app in development mode. It only resolves to the index.html file. I have looked through CRA source code and can't really find any relevant place where asset-manifest.json is mentioned.
So how do I get webpack-dev-server to serve my assets.json file?
You need to add the ManifestPlugin to webpack.plugins.remove array to receive only the configuration from WebpackManifestPlugin:
...
webpack: {
alias: {},
plugins: {
add: [
new WebpackManifestPlugin(webpackManifestConfig)
],
remove: [
"ManifestPlugin"
],
},
configure: (webpackConfig, { env, paths }) => { return webpackConfig; }
},
...

Uncaught ReferenceError: webpackJsonp in Vue Js

I have suddenly started hitting Uncaught ReferenceError: webpackJsonp in Vue Js. I am fairly new to Js and have just started with Vue applications. I tried the various solutions that were mentioned in the Git and stackoverflow but they have not worked. Can someone help me out.
To give some context, the issue suddenly appeared without having made much of a change. The code is working when it was in the state earlier but making any change in the components even modifying the css has started causing the issue.
Based on what I read about the issue, it is supposed to be controlled by the webpack.prod.conf.js (Attached mine below). Incase any other info is needed please let me know.
"use strict";
const path = require("path");
const utils = require("./utils");
const webpack = require("webpack");
const config = require("../config");
const merge = require("webpack-merge");
const baseWebpackConfig = require("./webpack.base.conf");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const OptimizeCSSPlugin = require("optimize-css-assets-webpack-plugin");
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const env = require("../config/prod.env");
const webpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({
sourceMap: config.build.productionSourceMap,
extract: true,
usePostCSS: true
})
},
devtool: config.build.productionSourceMap ? config.build.devtool : false,
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath("js/[name].[chunkhash].js"),
chunkFilename: utils.assetsPath("js/[id].[chunkhash].js")
},
plugins: [
// http://vuejs.github.io/vue-loader/en/workflow/production.html
new webpack.DefinePlugin({
"process.env": env
}),
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false
}
},
sourceMap: config.build.productionSourceMap,
parallel: true
}),
// extract css into its own file
new ExtractTextPlugin({
filename: utils.assetsPath("css/[name].[contenthash].css"),
// Setting the following option to `false` will not extract CSS from codesplit chunks.
// Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
// It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
// increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
allChunks: true
}),
// Compress extracted CSS. We are using this plugin so that possible
// duplicated CSS from different components can be deduped.
new OptimizeCSSPlugin({
cssProcessorOptions: config.build.productionSourceMap ?
{ safe: true, map: { inline: false } } :
{ safe: true }
}),
// generate dist index.html with correct asset hash for caching.
// you can customize output by editing /index.html
// see https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: config.build.index,
template: "index.html",
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
// more options:
// https://github.com/kangax/html-minifier#options-quick-reference
},
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: "dependency"
}),
// keep module.id stable when vendor modules does not change
new webpack.HashedModuleIdsPlugin(),
// enable scope hoisting
new webpack.optimize.ModuleConcatenationPlugin(),
// split vendor js into its own file
new webpack.optimize.CommonsChunkPlugin({
name: "vendor",
async: false,
minChunks(module) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(path.join(__dirname, "../node_modules")) === 0
);
// return module.context && module.context.includes("node_modules");
}
}),
// This instance extracts shared chunks from code splitted chunks and bundles them
// in a separate chunk, similar to the vendor chunk
// see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
new webpack.optimize.CommonsChunkPlugin({
name: "app",
async: "vendor-async",
children: true,
minChunks: 3
}),
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
new webpack.optimize.CommonsChunkPlugin({
name: "manifest",
async: false,
minChunks: Infinity
}),
// copy custom static assets
new CopyWebpackPlugin([{
from: path.resolve(__dirname, "../static"),
to: config.build.assetsSubDirectory,
ignore: [".*"]
}])
]
});
if (config.build.productionGzip) {
const CompressionWebpackPlugin = require("compression-webpack-plugin");
webpackConfig.plugins.push(
new CompressionWebpackPlugin({
asset: "[path].gz[query]",
algorithm: "gzip",
test: new RegExp(
"\\.(" + config.build.productionGzipExtensions.join("|") + ")$"
),
threshold: 10240,
minRatio: 0.8
})
);
}
if (config.build.bundleAnalyzerReport) {
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
.BundleAnalyzerPlugin;
webpackConfig.plugins.push(new BundleAnalyzerPlugin());
}
module.exports = webpackConfig;
The entry points are missing in the configuration, i.e. you are not informing webpack from where the application should start.
Also this issue is happening because you have mentioned vendor
please refer this link

How to enable dotenv variables for a file inside the /public folder in a Vue project?

I have very little experience with configuring Webpack, and I'am a bit overwhelmed by this issue.
I've been working on a Vue2 project built on top of this boilerplate. The project has a folder called public which contains the entry point file index.html. Inside that index.html file I can normally access .env environment variables (e.g. process.env.VUE_APP_PAGE_TITLE).
I've included an HTML fragment inside the public folder, navbar.html, because I want it to be available for other applications via https://example.com/public/navbar.html. However, I cannot seem to get my environment variables working inside ./public/navbar.html even though they work just fine in ./public/index.html. I assume this is a problem with my webpack config.
I know I can edit my Webpack config by editing a file in my project root called vue.config.js. This file contains a configureWebpack object, but I have no idea how to make it enable environment variables inside ./public/navbar.html. Any help would be appreciated.
EDIT:
Here's my vue.config.js:
const HtmlWebpackPlugin = require('html-webpack-plugin');
function resolveClientEnv() {
const env = {};
Object.keys(process.env).forEach((key) => {
env[key] = process.env[key];
});
env.BASE_URL = '/';
return env;
}
module.exports = {
configureWebpack: {
plugins: [
new HtmlWebpackPlugin({
// This is the generated file from the build, which ends up in public/navbar.html
filename: 'navbar.html',
// This is the source file you edit.
template: 'public/navbar.html',
templateParameters: (compilation, assets, pluginOptions) => {
let stats;
return Object.assign({
// make stats lazy as it is expensive
get webpack() {
return stats || (stats = compilation.getStats().toJson());
},
compilation,
webpackConfig: compilation.options,
htmlWebpackPlugin: {
files: assets,
options: pluginOptions,
},
}, resolveClientEnv());
},
}),
],
},
};
This is what my custom HTMLWebpackPlugin adds to the configuration according to vue inspect:
{
options: {
template: 'public/navbar.html',
templateContent: false,
templateParameters: function () { /* omitted long function */ },
filename: 'navbar.html',
hash: false,
inject: true,
compile: true,
favicon: false,
minify: 'auto',
cache: true,
showErrors: true,
chunks: 'all',
excludeChunks: [],
chunksSortMode: 'auto',
meta: {},
base: false,
title: 'Webpack App',
xhtml: false
},
childCompilerHash: undefined,
childCompilationOutputName: undefined,
assetJson: undefined,
hash: undefined,
version: 4
}
Use this standard plugin to generate navbar.html. https://github.com/jantimon/html-webpack-plugin.
If you read the docs, the templateParameters option is what you pass env variables to. Those variables will be available in navbar.html.
This is the same plugin that vue-cli uses for index.html. If you run the vue inspect command, you can see what options they provide to the plugin. You'll need to read the source code for resolveClientEnv() to see how it works.
Example:
/* config.plugin('html-portal') */
new HtmlWebpackPlugin(
{
templateParameters: (compilation, assets, pluginOptions) => {
// enhance html-webpack-plugin's built in template params
let stats
return Object.assign({
// make stats lazy as it is expensive
get webpack () {
return stats || (stats = compilation.getStats().toJson())
},
compilation: compilation,
webpackConfig: compilation.options,
htmlWebpackPlugin: {
files: assets,
options: pluginOptions
}
}, resolveClientEnv(options, true /* raw */))
},
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true,
collapseBooleanAttributes: true,
removeScriptTypeAttributes: true
},
chunks: [
'chunk-vendors',
'chunk-common',
'portal'
],
template: 'C:\\Users\\Eric\\workspace\\arc-core\\portal\\client\\templates\\portal.html',
filename: 'portal.html',
title: 'Arc Portal'
}
),
That's a bit much, a minimal example would be:
new HtmlWebpackPlugin({
// This is the generated file from the build, which ends up in public/navbar.html
filename: 'navbar.html',
// This is the source file you edit.
template: 'templates/navbar.html',
templateParameters: {
MY_VAR: 'myVar'
}
}),

Vue Cli 3 build custom directory for different type of files

I am new in using vue to build web app.
By default, use npm run build, it will build the following structure:
But I hope to build as follow:
Then, how can I write the vue.config.js as output like what I want?
Using this GitHub issue as an example, you should be able to achieve this by adding something like this to your configuration...
// vue.config.js
module.exports = {
chainWebpack: config => {
config.module.rule('images').use('url-loader')
.loader('file-loader') // replaces the url-loader
.tap(options => Object.assign(options, {
name: 'images/register/[name].[hash:8].[ext]'
}))
config.module.rule('svg').use('file-loader')
.tap(options => Object.assign(options, {
name: 'images/register/[name].[hash:8].[ext]'
}))
},
css: {
extract: {
filename: 'css/register/[name].[hash:8].css',
chunkFilename: 'css/register/[name].[hash:8].css'
}
},
configureWebpack: {
output: {
filename: 'js/register/[name].[hash:8].js',
chunkFilename: 'js/register/[name].[hash:8].js'
}
}
}
See https://cli.vuejs.org/config/#vue-config-js for more information and examples.