{"id":22119555,"url":"https://github.com/ferrywlto/vue-plugin-demo","last_synced_at":"2026-05-08T18:33:10.343Z","repository":{"id":38260625,"uuid":"274140552","full_name":"ferrywlto/Vue-Plugin-Demo","owner":"ferrywlto","description":"Demostrate how to create a Vue plugin to achive code reuse across projects.","archived":false,"fork":false,"pushed_at":"2022-12-13T03:23:33.000Z","size":972,"stargazers_count":0,"open_issues_count":21,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-03-16T17:16:31.249Z","etag":null,"topics":["github-package-registry","npm-package","package","plugin","vue","vuex"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ferrywlto.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-06-22T13:11:51.000Z","updated_at":"2022-02-19T05:22:00.000Z","dependencies_parsed_at":"2023-01-28T05:45:26.886Z","dependency_job_id":null,"html_url":"https://github.com/ferrywlto/Vue-Plugin-Demo","commit_stats":null,"previous_names":["verdantsparks/vue-plugin-demo"],"tags_count":0,"template":false,"template_full_name":"ferrywlto/VueCLI-Base-Project-Template","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ferrywlto%2FVue-Plugin-Demo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ferrywlto%2FVue-Plugin-Demo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ferrywlto%2FVue-Plugin-Demo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ferrywlto%2FVue-Plugin-Demo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ferrywlto","download_url":"https://codeload.github.com/ferrywlto/Vue-Plugin-Demo/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245219039,"owners_count":20579526,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["github-package-registry","npm-package","package","plugin","vue","vuex"],"created_at":"2024-12-01T14:15:14.686Z","updated_at":"2026-05-08T18:33:10.277Z","avatar_url":"https://github.com/ferrywlto.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Vue Plugin Demostration Project.\n\n### Note: This guide only talk about creating JavaScript package. Although you can write the package in Typescript, since there are some difficulties on generating the `index.d.ts` declaration file for Single File Component (`.vue` files) in Vue (unless you need to config `rollup` as well), the produceded pacakge by this guide will lack the `index.d.ts` file and thus not able to import in `.ts` file. Therefore we do not recommend spending effort to make Typescript consumable package.\n\nThe files we need in this demo:\n\n![File structure.](https://github.com/VerdantSparks/Vue-Plugin-Demo/blob/master/doc/structure.png)\n\nThis project will create a most basic Vue plugin, it consist a Vuex store, and two SFC that read the vuex store. Build, pack and publish them as NPM package and finally consume it back from NPM registry.\n\n## Creating the plugin:\n```\n// myPlugin/myComponentA.vue\n\u003ctemplate\u003e\n    \u003cdiv\u003eFoo: {{getSharedStoreState}}\u003c/div\u003e\n\u003c/template\u003e\n\n\u003cscript\u003e\n    export default {\n        name: 'component-a',\n        computed: {\n            getSharedStoreState() {\n                return this.$store.state.my_store.foo - 1;\n            }\n        }\n    };\n\u003c/script\u003e\n```\n\n```\n// myPlugin/myComponentB.vue\n\u003ctemplate\u003e\n    \u003cdiv\u003eBar: {{getSharedStoreState}}\u003c/div\u003e\n\u003c/template\u003e\n\n\u003cscript\u003e\n    export default {\n        name: 'component-b',\n        computed: {\n            getSharedStoreState() {\n                return this.$store.state.my_store.foo + 1;\n            }\n        }\n    };\n\u003c/script\u003e\n```\n\n```\n// myPlugin/store.js\nconst store = {\n    namespaced: true,\n    state: {\n        foo: 123,\n    }\n};\n\nexport default store;\n```\n\n``` \n// myPlugin/index.js\nimport componentA from './myComponentA';\nimport componentB from './myComponentB';\nimport myStore from './store.js'\n\nconst MyPlugin = {\n    install(Vue, rootStore) {\n        // Vue is a Vue Constructor, not an Vue instance. This plugin requires passing the main app Vue instance as options parameter.\n\n        // Vue.component need to be called BEFORE new Vue() in main.js...\n        Vue.component(componentA.name, componentA);\n        Vue.component(componentB.name, componentB);\n\n        const storeName = 'my_store';\n\n        // While app only available AFTER new Vue() in main.js...\n        // Add store only once.\n        if(!rootStore.hasModule(storeName)) {\n            rootStore.registerModule(storeName, ProximityStore);\n        }\n    }\n}\n\nexport default MyPlugin;\n\nexport {componentA, componentB}\n\n// Automatic installation if Vue has been added to the global scope.\nif (typeof window !== 'undefined' \u0026\u0026 window.Vue) {\n    window.Vue.use(MyPlugin)\n}\n```\n\n## Installing the plugin:\n\n```\n// main.js\nimport Vue from 'vue'\nimport App from './App.vue'\nimport myPlugin from \"./myPlugin/index.js\"\nimport Vuex from 'vuex'\nimport rootStore from './store.js';\nVue.use(Vuex);\n\nVue.use(myPlugin, rootStore);\n\nnew Vue({\n  render: h =\u003e h(App),\n  store: rootStore,\n}).$mount('#app');\n\n```\n** Why need to pass `rootStore` as parameter? **\nThis is because you are not able to access Vuex store BEFORE new Vue() instance created in the install() method inside plugin.\nIn-addition, global component registration MUST perform ahead of new Vue(). \n\n```\n// store.js\nimport Vue from 'vue';\nimport Vuex from 'vuex'\nVue.use(Vuex);\n\nconst store = new Vuex.Store({\n    state: {\n        bar: 456,\n    },\n    modules: {\n        a: {\n            namespaced: true,\n            state: {\n                hello: 'world',\n            }\n        },\n    },\n});\n\nexport default store;\n```\n\n## Validate it works.\n``` \n// App.vue, styles omitted.\n\u003ctemplate\u003e\n  \u003cdiv id=\"app\"\u003e\n    \u003cimg alt=\"Vue logo\" src=\"./assets/logo.png\"\u003e\n    \u003cHelloWorld msg=\"Welcome to Your Vue.js App\"/\u003e\n  \u003c/div\u003e\n\u003c/template\u003e\n\n\u003cscript\u003e\nimport HelloWorld from './components/HelloWorld.vue'\n\nexport default {\n  name: 'App',\n  components: {\n    HelloWorld\n  },\n}\n\u003c/script\u003e\n```\n\n``` \n// components/HelloWorld.vue\n\u003ctemplate\u003e\n  \u003cdiv class=\"hello\"\u003e\n    {{msg}}\n    \u003ccomponent-a/\u003e\n    \u003ccomponent-b/\u003e\n  \u003c/div\u003e\n\u003c/template\u003e\n\n\u003cscript\u003e\nexport default {\n  name: 'HelloWorld',\n  props: {\n    msg: String\n  }\n}\n\u003c/script\u003e\n```\n\nNow plugin has installed, the components from plugin can be used and the components can access the plugin's vuex store.\nThe plugin's vuex store has been registered as nested store of root store successfully.\n\n![Plugin worked.](https://github.com/VerdantSparks/Vue-Plugin-Demo/blob/master/doc/result.png)\n\n## Pack and publish this plugin\n\n1. Build your plugin as library and use the plugin definition file as input by:\n\n`vue-cli-service build --target lib --name myPlugin ./src/myPlugin/index.js`\n\nYou should see something similar:\n\n![Build output.](https://github.com/VerdantSparks/Vue-Plugin-Demo/blob/master/doc/build-output.png)\n\nYour `dist` folder should now have these files created:\n\n![Files in dist folder.](https://github.com/VerdantSparks/Vue-Plugin-Demo/blob/master/doc/dist-files.png)\n\n2. Update `package.json`:\n\nTo save time so you don't have to type the whole build command, I add this in `script` section:\n\n`\"build-plugin\": \"vue-cli-service build --target lib --name myPlugin ./src/myPlugin/index.js\"`\n\nthe whole `script` section now looks like:\n\n```\n  \"scripts\": {\n    \"serve\": \"vue-cli-service serve\",\n    \"build\": \"vue-cli-service build\",\n    \"lint\": \"vue-cli-service lint\",\n    \"build-plugin\": \"vue-cli-service build --target lib --name myPlugin ./src/myPlugin/index.js\"\n  },\n```\nThere are some important fields we need to add in order to publish our package successfully:\n\n- name\n  \n  You package name that will discover by other developers.\n  \n- version\n\n  Specify your package version in semver format. Note that you cannot pushing package with the same or older version number to NPM. Thus you need to update it whenever before you attempt to update the package.\n  \n- license\n\n  Specify your package license, e.g. this repo is MIT license.\n   \n- repository\n\n  Specify your package repository url, e.g. this GitHub repository url.\n  \n- private\n\n  Specify does this package can discover by public, gotta set to `false` otherwise `yarn publish` or `npm publish` will not work.\n  \n- **files**\n\n  Specify what files you want to include in the published package, some will include the source of their package as well for easier debugging. For this demo we just keep the built files.\n  \n- **main**\n\n  Highly important, specify the file to load when someone import your plugin.\n  For example, if I set: \n\n  `\"main\": \".dist/myPlugin.common.js\",` instead of `\"main\": \"./dist/myPlugin.common.js\",`\n  \n  The developer who consume your package will encounter this when they `yarn serve`:\n\n  ![Dependency not found.](https://github.com/VerdantSparks/Vue-Plugin-Demo/blob/master/doc/dep-not-found.png)\n\n  **Really make sure the `main` field has correctly set.**\n\nOur resulting `package.json` should look like this:\n\n```\n{\n  \"name\": \"vue-plugin-demo-pkg\",\n  \"version\": \"0.1.5\",\n  \"private\": false,\n  \"scripts\": {\n    \"serve\": \"vue-cli-service serve\",\n    \"build\": \"vue-cli-service build\",\n    \"lint\": \"vue-cli-service lint\",\n    \"build-plugin\": \"vue-cli-service build --target lib --name myPlugin ./src/myPlugin/index.js\"\n  },\n  \"main\": \"./dist/myPlugin.common.js\",\n  \"files\": [\n    \"dist/*\"\n  ],\n  \"license\": \"MIT\",\n  \"repository\": \"https://github.com/VerdantSparks/Vue-Plugin-Demo\",\n  ... omitted\n}\n```\n  \n3. run `yarn publish`\n\nIf you did not login before, you should do that via `yarn login`.\n\n### NOTE: You need to have a NPM account and have your email verified before you can push any package to NPM. Otherwise you will see this the following error during publish (and receive an email from NPM):\n\n![Email not verified.](https://github.com/VerdantSparks/Vue-Plugin-Demo/blob/master/doc/verify-email.png)\n\nYou should see something similar if you pushed your package successfully.\n\n![Package published.](https://github.com/VerdantSparks/Vue-Plugin-Demo/blob/master/doc/push-success.png)\n\nLet's see your package information via `yarn info \u003cyour_package_name\u003e`\n\n![Package information.](https://github.com/VerdantSparks/Vue-Plugin-Demo/blob/master/doc/package-info.png)\n\nThe resulting npm package can be found [here](https://www.npmjs.com/package/vue-plugin-demo-pkg).\n\n## Installing your own plugin from NPM \n\n1. Run `yarn add vue-plugin-demo-pkg`\n\n2. Update `main.js`:\n\nchange `import myPlugin from \"./myPlugin/index\"`\n\nto `import myPlugin from \"vue-plugin-demo-pkg\"`\n\n3. Run `yarn serve`\n\n4. You should find that the plugin is load from `node_module` and works exactly the same as you reference it locally.\n\n# 🎉 Congratulations 🎉  \n\nYou have learned how to create your great Vue plugin and publish it to NPM ‼ 🍺\n\n## One more thing. 👀\n\n### Publish the plugin to GPR (GitHub Package Registry)\n\n1. Update package.json, add:\n\n```\n  \"publishConfig\": {\n    \"registry\": \"https://npm.pkg.github.com/@\u003cYOUR_USERNAME_OR_ORG_NAME\u003e\"\n  },\n```\n\nThis is not the same as the package tag in your repository stated. \n![GPR default.](https://github.com/VerdantSparks/Vue-Plugin-Demo/blob/master/doc/gpr-default.png)\n\n## EDIT 20210108: Since GPR was changed, you need to use the following setting in your `package.json`.\n```\n  \"name\": \"@\u003corganization_name\u003e/\u003cpackage_name\u003e\",\n  \"repository\": \"https://github.com/\u003corganization_name\u003e/\u003crepo_name\u003e\",\n  \"publishConfig\": {\n    \"registry\": \"https://npm.pkg.github.com\"\n  },\n```\n\nThis error will occur otherwise:\n![Name not match error.](https://github.com/VerdantSparks/Vue-Plugin-Demo/blob/master/doc/not-match.png)\n\n2. Login npm of GPR:\n\n`npm login --registry=https://npm.pkg.github.com --scope=@\u003cYOUR_USERNAME_OR_ORG_NAME\u003e`\n\nNOTE: if you omitted the `--scope` switch, you will encounter a 404 not found error when you `npm publish`\n\n![404 error.](https://github.com/VerdantSparks/Vue-Plugin-Demo/blob/master/doc/not-found.png)\n\n3. Push your plugin to GPR: `npm publish`\n\n![GitHub default.](https://github.com/VerdantSparks/Vue-Plugin-Demo/blob/master/doc/gpr-success.png)\n\n4. Consume the plugin from GPR:\n\n  4.1 Create a new Vue project from Vue CLI: `vue create \u003capp_name\u003e`\n  \n  4.2 Login GPR npm registry:\n  \n  `npm login --registry=https://npm.pkg.github.com/ --scope=@\u003cYOU_OR_ORG_GITHUB_NAME\u003e`\n  \n  4.3 Install the plugin from GPR:\n  \n  `npm i @\u003cYOU_OR_ORG_GITHUB_NAME\u003e/vue-plugin-demo-pkg`\n\n  4.4 Update code to use the plugin:\n\n```\n// in main.js\nimport Vue from 'vue'\nimport App from './App.vue'\nimport Vuex from 'vuex';\nVue.use(Vuex);\nconst rootStore = new Vuex.Store();\n\nimport MyPlugin from '@VerdantSparks/vue-plugin-demo-pkg'\nVue.use(MyPlugin, rootStore);\nVue.config.productionTip = false\n\nnew Vue({\n  store: rootStore,\n  render: h =\u003e h(App),\n}).$mount('#app')\n\n\n// in HelloWorld.vue\n\u003ctemplate\u003e\n    ...omitted\n        \u003ccomponent-a/\u003e\n        \u003ccomponent-b/\u003e\n    \u003c/div\u003e\n\u003c/template\u003e\n\n// in package.json\n    ...omitted\n    \"dependencies\": {\n    \"@VerdantSparks/vue-plugin-demo-pkg\": \"^0.1.5\",\n    \"core-js\": \"^3.6.5\",\n    \"vue\": \"^2.6.11\"\n    },\n    ...omitted\n```\n\n5. Run the Vue app: `npm serve` \n\nYou should see the plugin works as expected. 😀\n\n## References\n- https://www.digitalocean.com/community/tutorials/vuejs-creating-custom-plugins\n- https://www.xiegerts.com/post/creating-vue-component-library-npm/\n- https://www.xiegerts.com/post/creating-vue-component-library-structure/\n- https://sebastiandedeyne.com/exposing-multiple-vue-components-as-a-plugin/\n- https://stackoverflow.com/questions/53089441/how-to-access-vuex-from-vue-plugin\n- https://www.digitalocean.com/community/tutorials/vuejs-vuex-dynamic-modules\n- https://www.5balloons.info/create-publish-you-first-vue-plugin-on-npm-the-right-way/\n- https://stackoverflow.com/questions/47540846/dependency-not-found-even-defined-in-package-json-and-node-modules\n- https://stackoverflow.com/questions/57938784/not-found-put-https-npm-pkg-github-com-package-name\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fferrywlto%2Fvue-plugin-demo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fferrywlto%2Fvue-plugin-demo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fferrywlto%2Fvue-plugin-demo/lists"}