Normally, Vue CLI with vue.config.js places the .js and .css assets in /dist/[css|js]/. However, I want the .js and .css files in the root dist folder.
I can get the .js file in the root folder with the following config:
module.exports = {
productionSourceMap: false,
filenameHashing: false,
configureWebpack: {
optimization: {
splitChunks: false
}
},
chainWebpack: config => {
config.externals({
...config.get("externals"),
moment: "moment"
});
config.output.filename("[name].js");
}
};
How do I do this with the .css file?
This can be accomplished with the following Vue CLI config (from vuejs/vue-cli#1967):
// vue.config.js
module.exports = {
chainWebpack: (config) => {
config.module
.rule('images')
.use('url-loader')
.tap(options => Object.assign({}, options, { name: '[name].[ext]' }));
},
css: {
extract: {
filename: '[name].css',
chunkFilename: '[name].css',
},
},
configureWebpack: {
output: {
filename: '[name].js',
chunkFilename: '[name].js',
}
}
}
Related
My Vue projects contains, in the public folder, a large index.html. Currently it is simply copied to the output folder when I build my project as described here.
How can I get webpack to minify it too like it does for all my other files?
I added this to my vue.config.js
module.exports = {
chainWebpack: config => {
config
.plugin('html')
.tap(args => {
if (process.env.NODE_ENV === 'production')
args[0].minify = {
minifyCSS: true,
minifyJS: true,
minifyURLs: true,
removeComments: true,
collapseWhitespace: true,
collapseBooleanAttributes: true,
removeScriptTypeAttributes: true,
removeAttributeQuotes: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true
};
return args;
})
},
... // Other configs
}
More details here
Having added also a vue.config.js next to my babel.config.js I realized that the code doesn't get transpiled to ES5 anymore, probably because babel.config.js is fully ignored once there's a vue.config.js (?)
How can I keep babel transpiling the code when building with the presets given while yet having a vue.config.js with other configurations?
babel.config.js
module.exports = {
presets: [['#vue/app', { useBuiltIns: 'entry', corejs: 'core-js#2' }]],
}
vue.config.js
const TerserPlugin = require('terser-webpack-plugin')
module.exports = {
configureWebpack: config => {
if (process.env.NODE_ENV === 'production') {
config.optimization.minimizer = [
new TerserPlugin({
terserOptions: {
// needed for vuex-typex to work in production:
keep_fnames: true,
},
}),
]
}
},
css: {
loaderOptions: {
sass: {
data: `#import "./src/core/style/core/_variables.scss";`,
},
},
},
runtimeCompiler: true,
}
I created a project typescript project with the Vue Cli.
I want to have a separated commands.html file that should contain the javascript code from a commands.ts file.
I put the commands.html file in the public folder, so it is copied to the dist folder when building the project.
The commands.ts file is in the root folder (in the same folder in that the public, src, node_modules, etc folders are).
Webpack should do the following:
Minify the commands.html file (like it is minifying the index.html)
Compile the commands.ts file to JavaScript
Put the generated JavaScript file to the dist/js folder
Put a script tag in the commands.html file that points to the generated JavaScript file
I tried the following:
I installed html-webpack-plugin
I created a vue.config.js file with the following code:
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
configureWebpack: {
entry: {
commands: './commands.ts',
},
plugins: [
new HtmlWebpackPlugin({
filename: 'commands.html',
template: './public/commands.html',
chunks: ['commands'],
minify: {
collapseWhitespace: true,
},
}),
],
},
};
That is doing everything correctly, but it also creates a script tag in the index.html file that points to the generated JavaScript file. I think the default Webpack config of Vue is compiling the commands.ts in the bundle that is injected in the index.html file. How can I stop it from doing that?
Found it out:
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
configureWebpack: {
entry: {
functionFile: './functionFile.ts',
},
plugins: [
new HtmlWebpackPlugin({
filename: 'functionFile.html',
template: './public/functionFile.html',
chunks: ['functionFile'],
minify: {
collapseWhitespace: true,
},
}),
],
devServer: {
https: true,
},
},
chainWebpack: (config) => {
config
.plugin('html')
.tap((args) => {
// eslint-disable-next-line no-param-reassign
args[0].excludeChunks = ['functionFile'];
return args;
});
},
};
I have the following vue.config.js:
module.exports = {
filenameHashing: false,
productionSourceMap: false,
outputDir: '../vuejs/',
configureWebpack: {
devtool: 'source-map',
output: {
filename: '[name].js'
}
},
pages: {
feature1: {
entry: 'src/f1.js',
template: 'public/feature.html',
filename: 'index1.html',
title: 'Feature 1',
chunks: ['chunk-vendors', 'chunk-common', 'feature1']
},
feature2: {
entry: 'src/f2.js',
template: 'public/feature.html',
filename: 'index2.html',
title: 'Feature 2',
chunks: ['chunk-vendors', 'chunk-common', 'feature2']
}
}
}
On npm run build it generates:
index1.html
index2.html
feature1.js
feature2.js
js/chunk-vendors.js
in the dist folder (../vuejs/)
How could I change the configuration so the file chunk-vendors.js would be placed in the root folder (where feature1.js and feature2.js are).
P.S. : (Extra question) I actually do not need the html files, as I embed the vue.js *.js into an existing application. Can I suppress the generation of the html files?
You can define an explicit chunkFilename; e.g:
module.exports = {
outputDir: 'my/custom/build/path/',
configureWebpack: (config) => {
config.output.filename = '[name].[hash:8].js';
config.output.chunkFilename = '[name].[hash:8].js';
}
}
Which should generate something like:
my/custom/build/path/app.216ad62b.js
my/custom/build/path/app.216ad62b.js.map
my/custom/build/path/chunk-vendors.6f85144f.js
my/custom/build/path/chunk-vendors.6f85144f.js.map
Hope this helps :)
I am not sure if this is a webpack issue, vue-loader for webpack issue or just something that I am doing wrong.
When I am running npm run build to build a distribution for my Vue.js application the CSS rules applied in the dist app are in different order then in my development environment thus my CSS overrides are different and app doesn't render right...
Here is demonstration for one element:
npm run dev - proper render
npm run build - improper render
UPDATE: added webpack config files
webpack.base.conf.js
var path = require('path')
module.exports = {
entry: {
app: './src/main.js'
},
output: {
path: path.resolve(__dirname, '../dist/static'),
publicPath: '/static/',
filename: '[name].js'
},
resolve: {
extensions: ['', '.js', '.vue'],
alias: {
'src': path.resolve(__dirname, '../src')
}
},
resolveLoader: {
root: path.join(__dirname, 'node_modules')
},
module: {
preLoaders: [
{
test: /\.vue$/,
loader: 'eslint',
exclude: /node_modules/
},
{
test: /\.js$/,
loader: 'eslint',
exclude: /node_modules/
}
],
loaders: [
{
test: /\.vue$/,
loader: 'vue'
},
{
test: /\.js$/,
loader: 'babel',
exclude: /node_modules/
},
{
test: /\.json$/,
loader: 'json'
},
{
test: /\.scss$/,
loaders: ['style', 'css?sourceMap', 'sass?sourceMap']
},
{
test: /\.(png|jp?g|gif|svg|woff2?|eot|ttf)(\?.*)?$/,
loaders: [
'url?limit=20000&name=[name].[ext]?[hash:7]',
'image-webpack?{progressive:true, optimizationLevel: 7, interlaced: false, pngquant:{quality: "65-90", speed: 4}}'
]
},
{
test: /\.html$/,
loader: 'html'
}
]
},
eslint: {
formatter: require('eslint-friendly-formatter')
},
vue: {
loaders: {
sass: 'style!css!sass?indentedSyntax'
}
},
stylus: {
use: [require('nib')()],
import: ['~nib/lib/nib/index.styl']
}
}
webpack.dev.conf.js
var webpack = require('webpack')
var config = require('./webpack.base.conf')
var HtmlWebpackPlugin = require('html-webpack-plugin')
// eval-source-map is faster for development
config.devtool = '#eval-source-map'
// add hot-reload related code to entry chunks
var polyfill = 'eventsource-polyfill'
var devClient = './build/dev-client'
Object.keys(config.entry).forEach(function (name, i) {
var extras = i === 0 ? [polyfill, devClient] : [devClient]
config.entry[name] = extras.concat(config.entry[name])
})
// necessary for the html plugin to work properly
// when serving the html from in-memory
config.output.publicPath = '/'
config.plugins = (config.plugins || []).concat([
// https://github.com/glenjamin/webpack-hot-middleware#installation--usage
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
// https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'src/index.html',
inject: true
})
])
module.exports = config
webpack.prod.conf.js
var webpack = require('webpack')
var config = require('./webpack.base.conf')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
var HtmlWebpackPlugin = require('html-webpack-plugin')
// naming output files with hashes for better caching.
// dist/index.html will be auto-generated with correct URLs.
config.output.filename = '[name].[chunkhash].js'
config.output.chunkFilename = '[id].[chunkhash].js'
// whether to generate source map for production files.
// disabling this can speed up the build.
var SOURCE_MAP = true
config.devtool = SOURCE_MAP ? 'source-map' : false
// generate loader string to be used with extract text plugin
function generateExtractLoaders (loaders) {
return loaders.map(function (loader) {
return loader + '-loader' + (SOURCE_MAP ? '?sourceMap' : '')
}).join('!')
}
// http://vuejs.github.io/vue-loader/configurations/extract-css.html
var cssExtractLoaders = {
css: ExtractTextPlugin.extract('vue-style-loader', generateExtractLoaders(['css'])),
less: ExtractTextPlugin.extract('vue-style-loader', generateExtractLoaders(['css', 'less'])),
sass: ExtractTextPlugin.extract('vue-style-loader', generateExtractLoaders(['css', 'sass'])),
stylus: ExtractTextPlugin.extract('vue-style-loader', generateExtractLoaders(['css', 'stylus']))
}
config.vue = config.vue || {}
config.vue.loaders = config.vue.loaders || {}
Object.keys(cssExtractLoaders).forEach(function (key) {
config.vue.loaders[key] = cssExtractLoaders[key]
})
config.plugins = (config.plugins || []).concat([
// http://vuejs.github.io/vue-loader/workflow/production.html
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
}),
new webpack.optimize.OccurenceOrderPlugin(),
// extract css into its own file
new ExtractTextPlugin('[name].[contenthash].css'),
// generate dist index.html with correct asset hash for caching.
// you can customize output by editing /src/index.html
// see https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: '../index.html',
template: 'src/index.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
// more options:
// https://github.com/kangax/html-minifier#options-quick-reference
}
})
])
module.exports = config
What helped me, was tapping into the html plugin config, by adding this to vue.config.js
chainWebpack: config => {
config
.plugin('html')
.tap(args => {
args[0].chunksSortMode = function (chunk1, chunk2) {
const order = ['first', 'second', 'third']
const order1 = order.indexOf(chunk1.names[0])
const order2 = order.indexOf(chunk2.names[0])
return order1 - order2
}
return args
})
},