I am trying to use Vue and Vite for my blog. To generate static pages I use ViteSSG. I migrated from Vue 2 with CLI and faced many problems.
There is a broken html import. Rollup tries to import all
html and from /posts
too. And rollup uses my
loader. So it can't parse result as html. I don't know how
to exclude all from posts. I found that Vite uses all html
files as start points. And Vite does not have option to
exclude or use just index.html. I sacrificed HTML posts.
Now there are only markdown.
Routes broken. Because I use filenames with dot in url. See pull 2634. I renamed posts.
Rollout has limitations for imports and does not like
post.md?more=true
. See
issue 4275. So I wrote new loader.
Problem with environments in template. For example I can't
write in my post process.
.
See
issue 9829. To solve that I do replacement in my loader before Vite
does.
content = content
.replace(/\bimport\.meta/g, 'import.<wbr/>meta')
.replace(/\bprocess\.env/g, 'process.<wbr/>env');
Dynamic imports and Rollup are two big problems.
npm run serve
doesn't use Rollup and the
import work. But build
brings new errors.
Now I found good combination of Vite, Vue and ViteSSG versions and I can build my blog. See my blog generator.
But I tried to update to Vite 4 and got new error. My dynamic import does not work. The post is loaded by ESM loader. And it says:
Unknown file extension ".md"
Why does program not respect plugins and my loader? I don't know. I will look for workaround.
UPDATE 2023-02-10
Workaround is removing the dynamic import.
./src/components/Post.vuefunction loadPostContent() {
content.value = defineAsyncComponent(() => import("../../posts/" + post!.fileName + ".md"));
}
Rollup does not like it. But it somehow worked before. Now it doesn't.
So I must explicitly import my components for posts. I can
do it in my virtual:posts
module. I create
the array of posts with meta information in this module.
It means I can create a bunch of imports.
./posts_loader.jslet imports = '';
for(let post of allPosts) {
const componentName = makeComponentName(post.slug);
imports = imports + `
import ${componentName} from '${post.path}';
`;
}
Then I add the loaded components to the array. And return the array with components.
./posts_loader.jslet addComponentToPost = 'const allPosts = [];';
for(let post of allPosts) {
const postVarName = makePostVarName(post.slug);
addComponentToPost = addComponentToPost + `
const ${postVarName} = ${JSON.stringify(post)};
${postVarName}.component = ${makeComponentName(post.slug)};
allPosts.push(${postVarName});
`;
}
return {
code: `
${imports}
${addComponentToPost}
export const posts = allPosts;
export const tags = ${JSON.stringify(allTags)};
export const routes = ${JSON.stringify(allRoutes)};
`
};
As result post.component
is a Vue component
processed by ./post_loader.js
. And I can use
it in Post.vue
.
./src/components/Post.vuefunction loadPostContent() {
content.value = post.component;
}
It is possible to make lazy imports.
./posts_loader.jsfor(let post of allPosts) {
const componentName = makeComponentName(post.slug);
imports = imports + `
const ${componentName} = () => import('${post.path}');
`;
}
./src/components/Post.vuefunction loadPostContent() {
content.value = defineAsyncComponent(post.component);
}
Now it generates a separate js file for each post.