3.0.0-rc.5
https://github.com/androiddrew/flaskme
Create a project with the following structure:
top_level/
โโโ backend
โย ย โโโ static
โย ย โโโ templates
โโโ vue_project
โโโ dist
โโโ public
โโโ src
```
With vue.config.js set to :
const path = require("path");
module.exports = {
outputDir: path.resolve('../../backend/static'),
assetsDir: './assets',
baseUrl: '/',
runtimeCompiler: undefined,
productionSourceMap: undefined,
parallel: undefined,
css: undefined,
chainWebpack: config => {
config.plugin('html')
.tap(args => {
args[0].filename = path.resolve('../backend/templates/index.html');
return args;
});
},
}
Build your vue_project. The result is creates an `index.html` with the correct paths in the href tags, but the static assets are placed relative to the default folder NOT the outputDir defined in your config file.
Setting the vue.config file to:
const path = require("path");
module.exports = {
outputDir: path.resolve('../../backend/static'),
assetsDir: '../../backend/static/assets',
baseUrl: '/',
runtimeCompiler: undefined,
productionSourceMap: undefined,
parallel: undefined,
css: undefined,
chainWebpack: config => {
config.plugin('html')
.tap(args => {
args[0].filename = path.resolve('../backend/templates/index.html');
return args;
});
},
}
Will place the static assets in the defined directory however the `index.html` href values are injected with the assetsDir path.
```
The expected behavior should be to have the assetsDir be a relative path from your outputDir. If the outputDir is undefined then assetsDir is a relative path from the default assetsDir
The assetsDir is being used for two separate items. 1. It is being used as the outputDir for the assets. 2. It is used in the url-loaders that inject your src/href/etc. values.
This directory setup above is for a Vuejs SPA client and a Python backend. The built files should be served by the backend, which necessitates their placement in the backend static and template folders. It is part of a python application that will be distributed as a python package.
Thanks for providing a reporduction, even if I had some trouble getting it to work since the outputPath provided didn't work as you describe.
However, I think I know where your problem lies.
Is that about right?
First of all, assetDir, which is meant to define a physical directory within the outputDir, in which to output the assets. So it's not the solution to your problem and can't be - and there's no other config option in vue.config.js that solves this either.
What you would instead need to do is to adjust the (file)name setting of all loaders & plugins that generate assets - so mainly all rules with a url-loader and file-loader (images) and the mini-css-extract-plugin.
Before we get to that though, I still have a question: are you really serving the final index.html, which is served to the user's browser, and the final asserts in the same relation to one another? What I mean by that: you seem to want to adjust the asset path to adjust for the different folders were the assets and the index.html are created in, but that doesn't have to be the same "path difference" that the browser sees later.
Edit: On second thought I thnk my proposal below will actually not solve that. Will try another look at it later
Anyway: You can run the following to get an overview of the config:
npx vue-cli-service inspect --rules --mode production
npx vue-cli-service inspect --plugins --mode-production
npx vue-cli-service --mode production > config.js
the last command will give you a config.js file that contains a detailed description of the whole config.
Adjusting the config would look something like this:
chainWebpack: config => {
// that would have to happen for a bunch of rules:
['images', 'media', 'fonts'].forEach(rule => {
config.module.rules(rule).use('url-loader')
.tap(options => {
options.name = path.join('your/relative/asset/path', options.name)
return options
})
})
// svg is the only one using file-loader
config.module.rules('svg').use('file-loader')
.tap(options => {
options.name = path.join('your/relative/asset/path', options.name)
return options
})
// and the extract-css plugin has to be adjusted as well.
config.plugin('extract-css').tap(([options]) => {
options.filename = path.join('your/relative/asset/path', options.filename)
return [options]
})
}
I can't tell you what your relative path should be since I have no idea what the
So your solution encouraged me to start over from scratch.
I was using the vue ui to run my build and I believe it is the source of the strange behavior I am seeing. When I use the below vue.config.js and run it via npm run build from the command line everything lands where I expected with the correct paths necessary to serve it up through a Python Flask app.
However, firing up vue ui in the same path then running the build task results in my index file being written to the one defined in the plugin override, but the assets get written to the default dist folder. It is as if the vue ui build task is ignoring the outputDir.
const path = require("path");
module.exports = {
outputDir: '../flaskme/static',
assetsDir: undefined,
baseUrl: process.env.NODE_ENV === 'production'
? '/static'
: '/',
runtimeCompiler: undefined,
productionSourceMap: undefined,
parallel: undefined,
css: undefined,
chainWebpack: config => {
// Change index.html output directory
if (process.env.NODE_ENV === 'production'){
config.plugin('html')
.tap(args => {
args[0].filename = path.resolve('../flaskme/templates/index.html');
return args;
});
}
},
}
Try outputDir: path.resolve(__dirname, '../../flaskme/static'),
@Akryum outputDir: path.resolve(__dirname, '../../flaskme/static') resolves to the correct path but it then creates the whole output dir as a subdirectory under the vue directory(which may be another bug). It does not resolve the issue with the vue ui build task as I found above. Using the vue ui with this line still disregards the outputDir and places assets in the default dist directory.
The command line and the ui build commands exhibit different behavior when the outputDir is set outside of the vue project. That is think is the issue I am reporting.
The index file problem is actually a problem in html-webpack-plugin: it's filename option does not support absolute paths. I'd suggest opening an issue there.
Absolute path for outputDir is fixed in e7602abf .
In addition, the index file location can now be configured individually via a new indexPath option.
Closing as with the above fixes assetsDir is working as intended.
I'm struggling with this to now it's time to deploy my migrated vue cli 2 to vue cli 3 SPA. I want to put the static files in ../../static but also have the assets served up from href="/static/js/app.a7as86ad8.js" etc. See https://forum.vuejs.org/t/baseurl-at-but-files-within-index-html-to-be-served-at-static/45777/4
On vue cli 2, I had:
build: {
...
// Paths
assetsRoot: path.resolve(__dirname, '../../../'),
assetsSubDirectory: 'static',
assetsPublicPath: '/',
so my SPA lived at app.example.com but within index.html files were served at /static/js and /static/css etc.
img paths are also wrong in the built files. They are not relative to anything so you can not move.
I was advised to use baseurl and adjust in my router config.
Most helpful comment
img paths are also wrong in the built files. They are not relative to anything so you can not move.