I am trying to create a vue component library using rollup and vuejs. It worked with vue2 but was unable to parse css with vue3. I have upgraded the dependency in package.json
package.json
{
"name": "vue2tslibrary",
"version": "0.1.59",
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"build:js": "rimraf dist && rollup -c && rollup -c --environment MINIFY"
},
"sideEffects": [
"*.css",
"*.scss"
],
"files": [
"dist",
"src"
],
"main": "dist/cjs/index.js",
"module": "dist/esm/index.js",
"unpkg": "dist/vueslib.min.js",
"dependencies": {
"@mathieustan/vue-datepicker": "^0.2.8",
"core-js": "^3.6.5",
"date-fns": "^2.16.1",
"vue": "^3.0.1",
"vue-router": "^4.0.0-beta.13",
"vue-slider-component": "^4.0.0-beta.2",
"vue-template-compiler": "^2.6.12",
"vuex": "^4.0.0-beta.4"
},
"devDependencies": {
"@babel/plugin-proposal-optional-chaining": "^7.12.1",
"@rollup/plugin-alias": "2.2.0",
"@rollup/plugin-babel": "^5.2.1",
"@rollup/plugin-commonjs": "^15.1.0",
"@rollup/plugin-image": "^2.0.5",
"@rollup/plugin-node-resolve": "^9.0.0",
"@rollup/plugin-url": "^5.0.1",
"@typescript-eslint/eslint-plugin": "^2.33.0",
"@typescript-eslint/parser": "^2.33.0",
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-plugin-router": "~4.5.0",
"@vue/cli-plugin-typescript": "~4.5.0",
"@vue/cli-plugin-vuex": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"@vue/compiler-sfc": "^3.0.1",
"@vue/eslint-config-standard": "^5.1.2",
"@vue/eslint-config-typescript": "^5.0.2",
"autoprefixer": "^9.8.6",
"cssnano": "^4.1.10",
"eslint": "^6.7.2",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.0",
"eslint-plugin-vue": "^6.2.2",
"node-sass": "^4.14.1",
"postcss": "^8.1.1",
"postcss-calc": "^7.0.3",
"postcss-color-function": "^4.1.0",
"postcss-cssnext": "^3.1.0",
"postcss-discard-comments": "^4.0.2",
"postcss-discard-empty": "^4.0.1",
"postcss-discard-unused": "^4.0.1",
"postcss-each": "^0.10.0",
"postcss-extend-rule": "^3.0.0",
"postcss-import": "^12.0.1",
"postcss-mixins": "^6.2.3",
"postcss-nested": "^4.2.1",
"postcss-rem": "^1.1.5",
"postcss-simple-vars": "^5.0.2",
"postcss-sort-media-queries": "^1.7.26",
"postcss-url": "^8.0.0",
"rollup": "1.17.0",
"rollup-plugin-analyzer": "^3.3.0",
"rollup-plugin-babel": "^4.4.0",
"rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-css-only": "^2.1.0",
"rollup-plugin-node-resolve": "^5.2.0",
"rollup-plugin-postcss": "^3.1.8",
"rollup-plugin-terser": "^7.0.2",
"rollup-plugin-typescript": "^1.0.1",
"rollup-plugin-typescript2": "^0.28.0",
"rollup-plugin-uglify": "^6.0.4",
"rollup-plugin-vue": "^6.0.0-beta.8",
"sass-loader": "^10.0.3",
"style-resources-loader": "1.3.3",
"typescript": "~3.9.3"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"@vue/standard",
"@vue/typescript/recommended"
],
"parserOptions": {
"ecmaVersion": 2020
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}
rollup.config.js
import vue from 'rollup-plugin-vue'
import node from '@rollup/plugin-node-resolve'
import cjs from '@rollup/plugin-commonjs'
import babel from '@rollup/plugin-babel'
import postcss from 'rollup-plugin-postcss'
import { terser } from 'rollup-plugin-terser'
import css from 'rollup-plugin-css-only'
import postcssImport from 'postcss-import'
import autoprefixer from 'autoprefixer'
import simplevars from 'postcss-simple-vars'
import nested from 'postcss-nested'
import postcssEach from 'postcss-each'
import postcssMixin from 'postcss-mixins'
import postcssColor from 'postcss-color-function'
import postcssCalc from 'postcss-calc'
import postcssextend from 'postcss-extend-rule'
import postcssDiscardComment from 'postcss-discard-comments'
import postcssDiscardEmpty from 'postcss-discard-empty'
import postcssUrl from 'postcss-url'
import postcssRem from 'postcss-rem'
import sortMedia from 'postcss-sort-media-queries'
import cssnano from 'cssnano'
import url from '@rollup/plugin-url'
import typescript from 'rollup-plugin-typescript2'
import analyze from 'rollup-plugin-analyzer'
import fs from 'fs'
import path from 'path'
const babelConfig = {
exclude: 'node_modules/**',
babelHelpers: true,
babelrc: false,
presets: [['@babel/preset-env', { modules: false }]]
}
const baseFolder = './src/'
const componentsFolder = 'components/'
const components = fs
.readdirSync(baseFolder + componentsFolder)
.filter((f) =>
fs.statSync(path.join(baseFolder + componentsFolder, f)).isDirectory()
)
const entries = {
index: './src/index.ts',
...components.reduce((obj, name) => {
obj[name] = (baseFolder + componentsFolder + name)
return obj
}, {})
}
const capitalize = (s) => {
if (typeof s !== 'string') return ''
return s.charAt(0).toUpperCase() + s.slice(1)
}
const vuePluginConfig = {
defaultLang: {
style: 'postcss',
script: 'ts'
},
transformAssetUrls: {
includeAbsolute: true
},
preProcessStyles: true,
compileTemplate: false,
template: {
isProduction: true,
compilerOptions: {
whitespace: 'condense'
}
},
style: {
postcssPlugins: [
autoprefixer,
postcssImport({
resolve (id, basedir) {
// resolve alias @css, @import '@css/style.css'
// because @css/ has 5 chars
if (id.startsWith('@css')) {
// basedir will resolve to /src/components
return path.resolve('src/assets/styles/css', id.slice(5))
}
// resolve node_modules, @import '~normalize.css/normalize.css'
// similar to how css-loader's handling of node_modules
// if (id.startsWith('~')) {
// return path.resolve(basedir, '../node_modules', id);
// }
// resolve relative path, @import './components/style.css'
return path.resolve(basedir, id)
}
}),
postcssEach,
postcssMixin,
simplevars,
postcssColor,
postcssCalc,
nested,
postcssextend,
postcssDiscardComment,
postcssDiscardEmpty,
postcssUrl({ url: 'inline' }),
postcssRem({
baseline: 16, // Default to 16
// convert: 'px', // Default to rem
fallback: true, // Default to false
precision: 6 // Default to 5
}),
sortMedia({
sort: 'mobile-first'
}),
autoprefixer({
overrideBrowserslist: '> 1%, IE 6, Explorer >= 10, Safari >= 7'
}),
cssnano({
zindex: false
})
]
}
}
export default () => {
const mapComponent = (name) => {
return [
{
input: baseFolder + componentsFolder + `${name}/index.ts`,
external: ['vue'],
output: {
format: 'umd',
name: capitalize(name),
file: `dist/components/${name}/index.js`,
exports: 'named',
globals: {
vue: 'Vue'
}
},
plugins: [
typescript(),
url({
include: [
'**/*.svg',
'**/*.png',
'**/*.gif',
'**/*.jpg',
'**/*.jpeg'
]
}),
node({
extensions: ['.vue', '.js', '.ts']
}),
cjs(),
vue(vuePluginConfig),
css(),
babel(babelConfig)
]
}
]
}
let config = [
{
input: entries,
external: ['vue'],
output: {
format: 'esm',
dir: 'dist/esm'
},
plugins: [
typescript(),
cjs(),
url({
include: [
'**/*.svg',
'**/*.png',
'**/*.gif',
'**/*.jpg',
'**/*.jpeg'
]
}),
node({
extensions: ['.vue', '.js', '.ts']
}),
vue(vuePluginConfig),
css(),
babel(babelConfig),
analyze(),
terser({
output: {
comments: '/^!/'
},
compress: {
defaults: true
}
})
]
},
{
input: entries,
external: ['vue'],
output: {
format: 'cjs',
dir: 'dist/cjs',
exports: 'named'
},
plugins: [
typescript(),
url({
include: [
'**/*.svg',
'**/*.png',
'**/*.gif',
'**/*.jpg',
'**/*.jpeg'
]
}),
node({
extensions: ['.vue', '.js', '.ts']
}),
vue(vuePluginConfig),
css(),
babel(babelConfig),
cjs()
]
},
// {
// input: 'src/index.ts',
// external: ['vue'],
// output: {
// format: 'umd',
// name: capitalize('vu'),
// file: 'dist/vueslib.js',
// exports: 'named',
// globals: {
// vue: 'Vue'
// }
// },
// plugins: [
// typescript(),
// url({
// include: [
// '**/*.svg',
// '**/*.png',
// '**/*.gif',
// '**/*.jpg',
// '**/*.jpeg'
// ]
// }),
// node({
// extensions: ['.vue', '.js', '.ts']
// }),
// vue(vuePluginConfig),
// babel(babelConfig),
// cjs()
// ]
// },
{
input: 'src/index.ts',
external: ['vue'],
output: {
format: 'esm',
file: 'dist/vueslib.esm.js'
},
plugins: [
typescript(),
url({
include: [
'**/*.svg',
'**/*.png',
'**/*.gif',
'**/*.jpg',
'**/*.jpeg'
]
}),
node({
extensions: ['.vue', '.js', '.ts', '.css']
}),
vue(vuePluginConfig),
css(),
babel(babelConfig),
cjs()
]
},
// individual components
...components.map((f) => mapComponent(f)).reduce((r, a) => r.concat(a), [])
]
if (process.env.MINIFY === 'true') {
config = config.filter((c) => !!c.output.file)
config.forEach((c) => {
c.output.file = c.output.file.replace(/\.js/g, '.min.js')
c.plugins.push(terser({
output: {
comments: '/^!/'
},
compress: {
defaults: true
}
}))
})
}
return config
}
ERROR SCREENSHOT
Component
<template>
<!-- @css/_app-partials.css-->
<div>
<p class="yellow" @click="test()"> I am Dummy Component
<span class="reda">asdasdas</span>
</p>
<span class="red">asdasdas</span>
<img :src="require('../../assets/img/icons/download.jpeg')" />
<div class="imgtest">
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, PropType } from 'vue'
export default defineComponent({
name: 'DummyComponent',
data () {
return {
text1: 'I am Text Component'
}
},
props: {
isValid: {
type: Boolean,
default: false
},
msg: {
type: Object as PropType<{foo: string; bar: string}>
}
},
methods: {
test (): void {
console.log('test1', this.$props.msg)
}
}
})
</script>
<style lang="postcss" scoped>
@import '../../assets/styles/css/_app-partials.css';
.yellow {
color: red;
.reda {
color: $black;
}
}
.red {
color: green;
}
.imgtest {
background-image: url('../../assets/img/icons/star-half.svg');
background-size: 100%;
width: 100px;
height: 100px;
}
</style>
github repository link
https://github.com/shubhadip/vue-typescript-component-library