Cannot use Vue component library with npm link - vue.js

I am building a Vue application and a Vue component library at the same time. So, I would like to setup the library with npm link so I don't have to keep publishing my library package and re-install it in my main application.
My package will be called #company/vue. I can publish it to npm and install/use it in my Vue app like this:
import Vue from 'vue';
import VueComponents from '#company/vue';
Vue.use(VueComponents);
And that works fine. I can access the components in my .vue files and all that.
However, if I follow the standard steps to linking my library:
cd path/to/library
npm link
cd path/to/application
npm link #company/vue
Upon starting dev mode, I get this warning:
export 'default' (imported as 'VueComponents') was not found in '#company/vue'
And of course, nothing in the page loads.
I have to imagine that I'm possibly bundling it wrong?
My build script looks like this:
vue-cli-service build --no-clean --target lib --name company-vue src/index.js
And my index.js that it refers to:
import './index.scss';
import * as components from './components/index.js';
const CompanyVue = {
install(Vue) {
if (this.installed) {
return;
}
this.installed = true;
for (let name in components) {
Vue.use(components[name]);
}
}
};
let GlobalVue = null;
if (typeof window !== 'undefined') {
GlobalVue = window.Vue;
}
else if (typeof global !== 'undefined') {
GlobalVue = global.Vue;
}
if (GlobalVue) {
GlobalVue.use(Plugin);
}
export * from './components';
export default CompanyVue;
This is just the standard way I've seen most libraries do it. And again, it works fine if I pull the package from npm.
This is the stuff related to my bundling in my package.json:
"files": [
"dist",
"src",
"!src/**/*.spec.js",
"!src/**/*.stories.js"
],
"main": "./dist/company-vue.common.min.js",
"module": "./dist/company-vue.umd.min.js",
"browser": "./dist/company-vue.umd.min.js",
"unpkg": "./dist/company-vue.umd.min.js"
And finally, my babel config for the component library:
module.exports = {
presets: ['#babel/preset-env'],
env: {
test: {
presets: [[
'#babel/preset-env',
{
targets: { node: "current" }
}
]]
}
}
}

i found a solution in this issue:
just add this to your vue.config.js in your project:
configureWebpack: {
resolve: {
symlinks:false //npm link
},
}

Related

Vite library mode entry points

My vite config looks like this.
I want to have two entry points, as you can see in build.lib.entry I have the entry for my library, in this case src/main.js, but I would also like to have one entry for my project because I am testing locally.
// vite.config.js
const path = require('path')
module.exports = {
build: {
lib: {
entry: path.resolve(__dirname, 'src/main.js'),
name: 'MyLib'
},
rollupOptions: {
// make sure to externalize deps that shouldn't be bundled
// into your library
external: ['vue'],
output: {
// Provide global variables to use in the UMD build
// for externalized deps
globals: {
vue: 'Vue'
}
}
}
}
}
I tried adding the following code inside module.exports, but it didn'T work.
entry: path.resolve(__dirname, 'src/app.js'),
https://vitejs.dev/guide/build.html#library-mode
In the vite discussions on github it seems you do it with something like this.
https://github.com/vitejs/vite/discussions/1736#discussioncomment-413068
build: {
rollupOptions: {
input: {
'entry-point-a': path.resolve(__dirname, 'src/entry-point-a.tsx'),
'entry-point-b': path.resolve(__dirname, 'src/entry-point-b.tsx'),
},
}
},
It looks like vite does not support multiple entries. You can use two vite configuration files.
eg. package.json :
"scripts": {
"build": "vite build --config vite.config.js",
"build:lib": "vite build --config vite-lib.config.js",
},

Uncaught Error: 'target' is a required option - Svelte

I'm building an NPM package for Svelte. With this package I export a couple of simple components:
import SLink from './SLink.svelte';
import SView from './SView.svelte';
export { SLink, SView };
This is before bundling them to a minified version using rollup.
Rollup config:
module.exports = {
input: 'src/router/index.ts',
output: {
file: pkg.main,
format: 'umd',
name: 'Router',
sourcemap: true,
},
plugins: [
svelte({
format: 'umd',
preprocess: sveltePreprocess(),
}),
resolve(),
typescript(),
terser(),
],
};
package.json (minus unnecessary info):
{
"name": "svelte-dk-router",
"version": "0.1.29",
"main": "dist/router.umd.min.js",
"scripts": {
"lib": "rollup -c lib.config.js",
},
"peerDependencies": {
"svelte": "^3.0.0"
},
"files": [
"dist/router.umd.min.js"
],
}
When I publish the package and test it, I get this error:
Uncaught Error: 'target' is a required option
at new SvelteComponentDev (index.mjs:1642)
at new Home (App.svelte:5)
at Z (router.umd.min.js:1)
at N (router.umd.min.js:1)
at new t.SView (router.umd.min.js:1)
at create_fragment (App.svelte:5)
at init (index.mjs:1476)
at new App (App.svelte:5)
at main.js:7
at main.js:9
Which seems to be something to do with mounting the component as target is used to mount:
const app = new App({ target: document.body })
The odd thing is, SLink on it's own works fine, mounts as it should etc., it's just SView that doesn't work.
SLink:
<script lang="ts">
import { writableRoute, changeRoute } from '../logic';
export let name: string = undefined,
path: string = undefined,
query: Record<string, string> = undefined,
params: Record<string, string> = undefined;
let routerActive: boolean;
writableRoute.subscribe(newRoute => {
if (newRoute.path === '*') return;
const matches = (path && path.match(newRoute.regex)) || newRoute.name === name;
routerActive = matches ? true : false;
});
</script>
<div
on:click={() => changeRoute({ name, path, query, params })}
class={routerActive ? 'router-active' : ''}>
<slot />
</div>
SView:
<script lang="ts">
import { writableRoute } from '../logic';
let component: any;
writableRoute.subscribe(newRoute => (component = newRoute ? newRoute.component : null));
</script>
<svelte:component this={component} />
I've tried the components uncompiled, as per these docs, but then the imports don't work.
Anyone have any idea how I can work around this issue?
I recently ran into this problem. I was setting up a new page and forgot the defer keyword on the script. I had:
<script src="/app/public/build/bundle.js"></script>
and it needed to be
<script defer src="/app/public/build/bundle.js"></script>
Notice the missing defer.
All components in a Svelte tree need to be compiled with the same Svelte compiler (i.e. same node_modules/svelte) all at once. This includes components from external libs like what you are trying to achieve. This is what is explained in the docs you've linked.
The main field of the package.json will expose the compiled components, for usage in a non Svelte app.
You also need a svelte field to expose the uncompiled version of the components, for consumption by a Svelte app. You can still export multiple Svelte components from a .js file.
package.json
{
"name": "svelte-dk-router",
"version": "0.1.29",
"main": "dist/router.umd.min.js",
"svelte": "src/index.js",
"scripts": {
"lib": "rollup -c lib.config.js",
},
"peerDependencies": {
"svelte": "^3.0.0"
},
"files": [
"dist/router.umd.min.js"
],
}
src/index.js
import SLink from './SLink.svelte';
import SView from './SView.svelte';
export { SLink, SView };
rollup-plugin-svelte will pick up the svelte field in your lib's package.json, so that import of Svelte components resolve correctly.
I don't know about your issue but I was getting the same error message for this reason:
In the template.html file located in the src folder, I removed the element that has the #sapper ID and replaced the %sapper.html% code inside the body tag. The next thing to do was to change the render target to the document.body, in the client.js file located in the src folder. I forgot to do this step and this was causing that error message.

Removing log from production mode is not working - react native

React native documentation state that
"You can also use this babel plugin that removes all the console.* calls. You need to install it first with npm i babel-plugin-transform-remove-console --save-dev, and then edit the .babelrc file under your project directory like this"
{
"env": {
"production": {
"plugins": ["transform-remove-console"]
}
}
}
I didn't find .babelrc file. Hence I made the following changes in babel.config.js file.
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
env: {
production: {
plugins: ["transform-remove-console"]
}
}
};
But it's not working for me. The logs are displayed when I've tested them in Android Studio. What went wrong here?
The documented approach didn't work for my existing project either, but it worked in a new test project. I tried numerous dependency upgrades, adding/removing deps, plugins, etc. trying to figure out the source of the problem, but no luck. So finally I went with this workaround:
module.exports = {
plugins: ['#babel/plugin-proposal-numeric-separator', 'lodash'].concat(
process.env.NODE_ENV === 'production' ? ['transform-remove-console'] : []
),
presets: [
'module:metro-react-native-babel-preset',
['#babel/env', { targets: { node: 6 } }]
]
};
This should work (recommended method)
const presets = ['module:metro-react-native-babel-preset'];
const plugins = ['module:react-native-dotenv'];
if (process.env.ENV === 'prod') {
plugins.push('transform-remove-console');
}
module.exports = {presets, plugins};
Or if you don't want to use any package for this you can do this.
Place this in index.js
if(!__DEV__){
console.log = () => {}
}

How to create my own component library based on Vuetify

I want create my component library based on Vuetify and publish on npm.
Vuetify has already vue-plugin standard installation and use vuetify-loader, I think was a more complex scenario than plain HTML component.
For example, I want create my Login Form, my Article Page, my default calendar picker with preset values.
There's a standard way or guide to do this or a sample to do that?
I use last version of vuetify (2.0.7)
I just got it working for Vue3/Vuetify3. In a nutshell (using pnpm, vite, typescript, Vue plugin):
Create the component as a new project:
pnpm create vue#latest
-> your-plugin
-> Typescript
-> ESLint
cd <project>
echo auto-install-peers = true > .npmrc
pnpm add -D vuetify rollup-plugin-typescript2
Then remove all the components and make your own component instead.
Create src\components\index.ts and src\YourPlugin.ts
src\components\index.ts
export {default as YourComponent} from "./YourComponent.vue"
src\YourPlugin.ts
import type { App } from "vue"
import { YourComponent } from "./components"
export default {
install: (app: App) => {
app.component("YourComponent", YourComponent)
}
};
vite.config.ts
Add to the imports:
import vuetify from 'vite-plugin-vuetify'
import typeScript2 from "rollup-plugin-typescript2"
Add to the plugins:
vuetify({
autoImport: true,
}),
typeScript2({
check: false,
include: ["src/components/*.vue"],
tsconfigOverride: {
compilerOptions: {
sourceMap: true,
declaration: true,
declarationMap: true,
}
},
exclude: [
"vite.config.ts"
]
})
Add a new section build to the defineConfig:
build: {
cssCodeSplit: false,
lib: {
entry: "./src/YourPlugin.ts",
formats: ["es", "cjs"],
name: "CommonVtfyPlugin",
fileName: format => (format == "es" ? "index.js" : "index.cjs"),
},
rollupOptions: {
external: ["vue", "vuetify/lib"],
output: {
globals: {
vue: "Vue",
vuetify: "Vuetify",
'vuetify/components': 'VuetifyComponents',
'vuetify/directives': 'VuetifyDirectives'
}
}
}
},
dist\index.d.ts
I have not figured out how to generate this on yet. But this is a generic stand in:
declare const _default: any;
export default _default;
package.json
Add this:
"type": "module",
"exports": {
".": "./dist/index.js"
},
"types": "./dist/index.d.ts",
"files": [
"dist"
],
You can use it in any Vue project by importing it as a plugin:
import YourComponent from 'your-plugin'
app.use(YourComponent)
No guarantees on how optimized that is (feedback welcome).. but it works (tm)..
A more detailed answer can be found pnpm monorepo: how to set up a simple reusable (vue) component for reuse? (any updates will primarily be updated in that answer as well, if any)

Vue CLI 3: Sourcemaps cannot be parsed by Chrome devtools

I built my simple site using Vue UI (the ones that comes with Vue-CLI 3), and it created sourcemaps in the /dist folder. I deploy these sourcemaps along with the production files. When I load up my site, Chrome indicates it cannot parse the sourcemaps in Devtools.
DevTools failed to parse SourceMap: https://www.thisisnotarealdomain.net/js/app.92ef018b.js.map
I have tried the following in vue.config.js:
module.exports = {
css: {
// modules: true,
loaderOptions: {
// pass options to sass-loader
sass: {
// #/ is an alias to src/
// so this assumes you have a file named `src/scss/variables.scss`
data: `#import "#/scss/_globals.scss";`
}
}
},
configureWebpack: {
devtool: '#source-map'
}
}
and
module.exports = {
css: {
// modules: true,
loaderOptions: {
// pass options to sass-loader
sass: {
// #/ is an alias to src/
// so this assumes you have a file named `src/scss/variables.scss`
data: `#import "#/scss/_globals.scss";`
}
}
},
configureWebpack: {
devtool: '#cheap-eval-source-map'
}
}
But Chrome still complains and I cannot see my original source.
I found some articles on the Internet regarding Webpack and Chrome interaction with sourcemaps, but I cannot tell if the problem has been resolved. Is there a problem with sourcemaps created by Vue UI?
Thanks.