TLDR: I wanna use rollupjs in a big application with vue components, in typescript, and other resources with inner and outer dependencies.
I have a Vue 2 application, with vue-property-decorators (so that means its all in typescript). It is a GIS application with Deck.gl and a custom UI using Buefy. It has a few steps of configuration (split in several components), and finally a Visualization, which has its own component (and sub components). Along this we have:
- a Vuex Store for these components shared resources
- A Vue router declaration for the navigation between the configs and visualization
- Interfaces, Classes and type declarations.
- Some global scss, scss variables, but also scoped scss inside the components.
All of this was somewhat tied also to CMS that provided the config options, that works fine in production. I managed to strip and refactor the Config and Visualization part to be self contained and should export everything so that we could hook up back into the CMS but also as a local application (like a tiny Vue app that only loads the main view of the GIS app), for academic purposes, so students can load their own data into it.
I was thinking of using rollupjs to bundle this library/self-contained-vue-project and that I could import it as a npm module into other projects.
I expect that I can do something like this:
// this is inside the GIS app and would be rolled up in a bundle.
import { ConfigComponent } from '@/components/component1';
import { ConfigComponent2 } from '@/components/component2';
import { VisualizationComponent } from '@/components/visualization';
function getRoutes(baseURL: string): RouteConfig[] {
return [
{
path: 'config',
name: 'ConfigComponent',
component: ConfigComponent
},
{
path: 'config2',
name: 'ConfigComponent2',
component: FlowDatasets
},
{
path: 'visualization',
name: 'VisualizationComponent ',
component: VisualizationComponent
}
]
}
// this is outside the library, and this should be typesafe too.
import { getRoutes } from '@gis_lib';
const baseRoute = 'base',
router = new Router({
routes: [
{
path: '/',
component: Main,
redirect: baseRoute,
children: [
...getRoutes(baseRoute)
]
}
],
mode: 'history'
});
export default router;
// and use this on my CMS or local app
After looking a bunch of examples, I'm still struggling a bit. Questions
- Should I transpile everything to js so that ?
- Should I expose all components or not, since only a few should be exposed, but they heavily rely on their children components to do stuff.
- What output do I need to import? the esm? the cjs? the main index.js file?
Here are some relevant files:
rollup.config.js - this is mostly based on buefy rollup file.
import vue from 'rollup-plugin-vue2';
import node from '@rollup/plugin-node-resolve';
import cjs from '@rollup/plugin-commonjs';
import scss from 'rollup-plugin-scss';
import babel from 'rollup-plugin-babel';
import alias from '@rollup/plugin-alias';
import ts from 'rollup-plugin-typescript2';
const capitalize = s => {
if (typeof s !== 'string') return '';
return s.charAt(0).toUpperCase() + s.slice(1);
},
lowercase = s => {
if (typeof s !== 'string') return '';
return s.toLowerCase();
},
baseFolder = './src/',
componentsFolder = 'components/js/',
components = [
'Action',
'ActionBar',
'ActionMenu',
'LanguagePicker',
'TooltipInfo',
'Deck',
'ConfigComponent',
'ConfigComponent2',
'VisualizationComponent'
],
external = [
'lodash',
'axios',
'vue',
'vue-class-component',
'vue-router',
'vue-i18n',
'proj4',
'reproject'
],
globals = {
axios: 'axios',
vue: 'Vue',
proj4: 'proj4',
reproject: 'reproject',
'vue-i18n': 'VueI18n'
},
tsConfig = {
check: false,
sourceMap: false
},
aliasConfig = { entries: [{ find: /^@\/(.+)/, replacement: './src/$1' }] },
scssConfig = {
prefix: `@import "./src/assets/sass/variables.scss";`
},
vuePluginConfig = { styleToImports: true },
babelConfig = {
exclude: 'node_modules/**',
runtimeHelpers: true,
babelrc: false,
presets: ['@vue/cli-plugin-babel/preset'],
plugins: ['@babel/plugin-proposal-optional-chaining', '@babel/plugin-syntax-dynamic-import']
},
entries = {
// main file in js
index: './src/main.js',
// components
...components.reduce((obj, name) => {
obj[name] = baseFolder + componentsFolder + lowercase(name);
return obj;
}, {})
};
export default () => {
const mapComponent = name => {
return [
{
input: baseFolder + componentsFolder + `${name}`,
external,
output: {
format: 'umd',
name: capitalize(name),
file: `dist/components/${lowercase(name)}/index.js`,
exports: 'named',
globals
},
plugins: [
ts(tsConfig),
vue(vuePluginConfig),
scss(scssConfig),
alias(aliasConfig),
babel(babelConfig),
node({
extensions: ['.vue', '.js']
}),
cjs()
]
}
];
};
const config = [
{
input: entries,
external,
output: {
format: 'esm',
dir: `dist/esm`
},
plugins: [
ts(tsConfig),
vue(vuePluginConfig),
scss(scssConfig),
alias(aliasConfig),
babel(babelConfig),
node({
extensions: ['.vue', '.js']
}),
cjs()
]
},
{
input: entries,
external,
output: {
format: 'cjs',
dir: 'dist/cjs',
exports: 'named'
},
plugins: [
ts(tsConfig),
vue(vuePluginConfig),
scss(scssConfig),
alias(aliasConfig),
babel(babelConfig),
node({
extensions: ['.vue', '.js']
}),
cjs()
]
},
{
input: 'src/main.js',
external,
output: {
format: 'iife',
name: capitalize('flow'),
file: 'dist/flow.js',
exports: 'named',
globals
},
plugins: [
ts(tsConfig),
vue(vuePluginConfig),
scss(scssConfig),
alias(aliasConfig),
babel(babelConfig),
node({
extensions: ['.vue', '.js']
}),
cjs()
]
},
{
input: 'src/main.js',
external,
output: {
format: 'esm',
file: 'dist/flow.esm.js',
inlineDynamicImports: true
},
plugins: [
ts(tsConfig),
vue(vuePluginConfig),
scss(scssConfig),
alias(aliasConfig),
babel(babelConfig),
node({
extensions: ['.vue', '.js']
}),
cjs()
]
},
// individual components
...components.map(f => mapComponent(f)).reduce((r, a) => r.concat(a), [])
];
return config;
};
main.ts file
import Vue_ from 'vue';
import * as components from './components';
export default (() => {
const Mod = {
install(Vue: typeof Vue_) {
// Components
Object.entries(components).forEach(([name, component]) => {
registerComponent(Vue, component, name);
});
}
};
return Mod;
})();
// export api client and interfaces and request classes for the api
export * from './api';
// export all components
export * from './components';
// export all types
export * from './types';
// export router
// export utils and others
export * from './utils';
export * from './errors';