Build a Vue component for "unpkg" - javascript

I want to publish my component on unpkg.com. Actually it is there, but not working. I tried to use the same build (umd) as for my npm build, but I think I would need a specific build for unpkg. Here are the relevant parts of my package.json now:
...
"main": "dist/vuePolar.umd.js",
"unpkg": "dist/vuePolar.umd.min.js",
"scripts": {
"package": "vue-cli-service build --target lib --name vuePolar src/components/Polar.vue",
...
}
I suspect I need to build a IIFE instead of an UMD file, but there is nothing like that in my dist folder:
demo.html
vuePolar.common.js
vuePolar.common.js.map
vuePolar.umd.js
vuePolar.umd.js.map
vuePolar.umd.min.js
vuePolar.umd.min.js.map
Any idea how to get a build that works with unkpg?

Actually, it is ok to publish your component as UMD. I had to register my component in the Vue instance, like so:
<div id="app">
<polar :item="3">hoi</polar>
</div>
<script>
var app = new Vue({
el: '#app',
components: { polar: vuePolar},
})
</script>
Now it works. I got confused by an example that did not require the component to be registered.

Related

DevExtreme in Nuxt3 failing during build

I am trying to include DevExtreme UI components into Nuxt 3 project. I took basic Nuxt3 app generated via npx nuxi init nuxt-app and started with bending it.
This is my test component with very basic DevExtreme menu:
<template>
<div id="container">
<dxMenu>
<dxItem icon="home" />
<dxItem text="O aplikaci" />
<dxItem icon="key" />
</dxMenu>
</div>
</template>
<script lang="ts">
import DxMenu, { DxItem } from 'devextreme-vue/menu.js';
import { defineComponent } from 'vue'
export default defineComponent({
components: {
DxMenu, DxItem
}
})
</script>
Then I just render the component in my app.vue. I have no other configuration related to that (apart from importing DevExtreme css file via nuxt.config.ts).
My nuxt.config.ts looks just like this:
import { defineNuxtConfig } from 'nuxt'
// https://v3.nuxtjs.org/api/configuration/nuxt.config
export default defineNuxtConfig({
css : [
'#/assets/css/dx.generic.zdd-scheme.css'
]
})
I was quite successful for dev environement - running npm run dev works like charm. But when I try npm run build it always fails.
The output looks like this:
i Client built in 11430ms 13:38:43
i Building server... 13:38:43
√ Server built in 4482ms 13:38:47
√ Generated public .output/public nitro 13:38:47
start Building server... nitro 13:38:47
ERROR Rollup error: Error: Cannot find module devextreme/ui/menu imported from file:///C:/ATOS_Projekty/ZDD/web-
ui/app/node_modules, file:///C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/nuxt/node_modules,
file:///C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/nitropack/node_modules, file:///C:/ATOS_Projekty/ZDD/web-ui/app/,
file:///C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/_index.js, file:///C:/ATOS_Projekty/ZDD/web-ui/app/node_modules,
file:///C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/nuxt/, file:///C:/ATOS_Projekty/ZDD/web-
ui/app/node_modules/nuxt/node_modules/_index.js, file:///C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/nuxt/node_modules,
file:///C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/nitropack/, file:///C:/ATOS_Projekty/ZDD/web-
ui/app/node_modules/nitropack/node_modules/_index.js, file:///C:/ATOS_Projekty/ZDD/web-
ui/app/node_modules/nitropack/node_modules
ERROR Error: Cannot find module devextreme/ui/menu imported from file:///C:/ATOS_Projekty/ZDD/web-ui/app/node_modules,
file:///C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/nuxt/node_modules, file:///C:/ATOS_Projekty/ZDD/web-
ui/app/node_modules/nitropack/node_modules, file:///C:/ATOS_Projekty/ZDD/web-ui/app/, file:///C:/ATOS_Projekty/ZDD/web-
ui/app/node_modules/_index.js, file:///C:/ATOS_Projekty/ZDD/web-ui/app/node_modules, file:///C:/ATOS_Projekty/ZDD/web-
ui/app/node_modules/nuxt/, file:///C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/nuxt/node_modules/_index.js,
file:///C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/nuxt/node_modules, file:///C:/ATOS_Projekty/ZDD/web-
ui/app/node_modules/nitropack/, file:///C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/nitropack/node_modules/_index.js,
file:///C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/nitropack/node_modules
at resolvePath (/C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/mlly/dist/index.mjs:1079:10)
at _resolve (/C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/nitropack/dist/shared/nitro.8d0213e3.mjs:304:22)
at Object.resolveId (/C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/nitropack/dist/shared/nitro.8d0213e3.mjs:348:34)
at async resolveId (/C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/rollup/dist/es/shared/rollup.js:21737:26)
at async ModuleLoader.resolveId (/C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/rollup/dist/es/shared/rollup.js:22037:19)
at async /C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/#rollup/plugin-commonjs/dist/es/index.js:773:14
at async Promise.all (index 0)
at async /C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/#rollup/plugin-commonjs/dist/es/index.js:765:30
at async rewriteRequireExpressionsAndGetImportBlock (/C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/#rollup/plugin-commonjs/dist/es/index.js:1312:28)
at async transformCommonjs (/C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/#rollup/plugin-commonjs/dist/es/index.js:1874:23)`
devextreme-vue/menu is importing from devextreme/ui/menu, but it looks like this module is not being passed through during build.
Do I have to declare the dependency somewhere in my code to notify build server to use it? I have tried various things already (like trying to convince Vite (rollup) not to perform tree shaking or to switch to Webpack instead), but always ending up with the same result. But maybe I just fail to do it correctly, I still have to learn a lot about how exactly the things work here. Any help/clues will be appreciated.
This is my package.json in case I shall change or install something there.
{
"private": true,
"scripts": {
"build": "nuxt build",
"dev": "nuxt dev",
"generate": "nuxt generate",
"preview": "nuxt preview",
"postinstall": "nuxt prepare",
"start": "nuxt start"
},
"devDependencies": {
"nuxt": "3.0.0-rc.8"
},
"dependencies": {
"devextreme": "22.1.4",
"devextreme-vue": "22.1.4"
}
}
EDIT: my node is 16.17.0 and npm 8.19.0, maybe the versions are relevant...
So the working solutuion appears to be adding a plugin, in my case named dx.client.ts, but it shouldn't matter, into /plugins folder which imports all necessary components and makes them globally available inside the application:
import { DxButton } from "devextreme-vue/button";
import { DxMenu, DxItem } from 'devextreme-vue/menu';
// the list goes on as the app grows
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp
.component("DxButton", DxButton)
.component("DxMenu", DxMenu)
.component("DxItem", DxItem);
// the list goes on as the app grows
});
I also had to add:
ssr: false
option into nuxt.config.ts, otherwise I ended up with Entry module cannot be external (devextreme-vue). error message during build.
So it has some limitations, but so far it works.
EDIT: it turned out, that while it works fine for some DevExtreme components without further adjustments, some components (like DxForm) also require to disable tree-shaking during Vite build - see how to do it. Otherwise the necessary files are lost in the build process and vague runtime error TypeError: f(...)[t] is not a function appears while rendering the component.
Thanks Stefan (stenet) for the right answer provided here

Vuejs / NuxtJs include components from dynamically set directory

I am using NuxtJs / VueJs
I have a problem where by i need to set the path of a component dynamically. Why I hear you ask ?
Well I am creating a set of sites that will use the same basic codebase but only the look and feel will differ and thus for each domain want to load the components from the specific dir. The basic component names etc will remain the same just want to be able to change a few things which are beyond just some v-if statements in the component or css.
eg.
Site1: sites/mysite/HomePageHero.vue
Site2: sites/yoursite/HomePageHero.vue
Now i know about dynamic components but the problem there is i will have to add each sites components to the page every time i create a new site and i dont want to do that. So the more sites I create the bigger that list will get.
I just want to set the site name in the .env add the components to the dir and it all works (or something similar)
So if you take my code below , i need the DYNAMICHERE to be dynamic. There is probably something simple that I am missing.
import HomePageHero from '#/components/sites/DYNAMICHERE/HomePageHero'
Just for clarification as per the first response to this . I have tried doing the following which doesn't obviously work
import HomePageHero from '#/components/sites/' + process.env.THEME . + '/HomePageHero'
I finally got some time to play around with this and I fixed the problem which was best for my solution using the following code
I am using dotenv to define the env variables
const HomePageHero = () => import('#/components/sites/' + process.env.WEBSITE_NAME + '/HomePageHero');
Hattip to this article:
https://vuedose.tips/tips/dynamic-imports-in-vue-js-for-better-performance/
There still may be a cleaner solution but this works well for me.
If you are using laravel then you have 1 option: process.env.YOUR_SITE
This is what we're doing:
declare site names in package.json
use same name for mongodb
import components and use the one that matches mongodb process.env name
"scripts": {
"siteOne": "cross-env MONGO_DB=siteOne API_URL=http://localhost:3000 MONGO_URL=mongodb://localhost NODE_ENV=development nodemon server/index.js --watch server",
"siteTwo": "cross-env MONGO_DB=siteTwo API_URL=http://localhost:3000 MONGO_URL=mongodb://localhost NODE_ENV=development nodemon server/index.js --watch server",
"build_siteOne": "MONGO_DB=siteOne nuxt build",
"build_siteTwo": "MONGO_DB=siteTwo nuxt build",
"start": "node server/index.js",
},
<template>
<div class="footer">
<div class="container">
<component :is="footerComponent"></component>
</div>
</div>
</template>
<script>
import Footer_siteOne from '~/components/Footer_siteOne.vue';
import Footer_siteTwo from '~/components/Footer_siteTwo.vue';
export default {
components: {
Footer_siteOne,
Footer_siteTwo,
},
computed: {
footerComponent: function() {
return 'Footer_'+process.env.MONGO_DB;
}
}
}
</script>

Render component straight into template

I have a React component, which I'm building with Webpack. The component is exported from index.js, which is the entry file in the module:
// packages/tnetennba/index.js
class Tnetennba extends React.Component {
render() {
return (
<div>good morning, that's a nice tnetennba</div>
)
}
}
export default Tnetennba
My webpack configs resides in different directory than the module (I'm using mono-repository), so the module itself doesn't have any build configuration files or templates to work with webpack-dev-server.
// packages/tnetennba/package.json
{
"name": "tnetennba",
"version": "0.0.1",
"main": "dist/index.js",
"scripts": {
"start": "webpack-dev-server --config ../config/webpack.dev.js --open",
"build": "webpack --config ../config/webpack.build.js"
}
}
However, I wan't to be able to work with the component in the dev mode, and I can achieve that using HtmlWebpackPlugin:
// packages/config/webpack.dev.js
module.exports = merge(common, {
mode: 'development',
...
plugins: [
new HtmlWebpackPlugin({
inject: true,
template: '../config/index.html' // <-- this path is relative, becuase webpack will be called from packages/tnetennba directory.
})
]
})
However, I have to put ReactDOM.render function call inside my module's index.js, to render component into template:
//...
export default Tnetennba
ReactDOM.render(<Tnetennba />, document.getElementById('root')) // <-- This shouldn't be here.
Question: Is there a way, that I can avoid calling render inside the module, while working in dev mode? Is is possible to call React renderer within webpack?
I would like to avoid conditional rendering using node's process variable as well.
Look at HtmlWebpackIncludeAssetsPlugin, it allows you to add an asset to the html file, my idea is to add a js file that will call ReactDom.render method inside it.
new HtmlWebpackPlugin(),
new HtmlWebpackIncludeAssetsPlugin({
assets: [
{ path: 'path/to/bootstrap.js', type: 'js' }
]
})

Vue.js - Compile .vue file with gulp

I have a Vue component. This component is very basic and looks like this:
my-component.vue
<template>
<div class="foo">
</div>
</template>
<script>
export default {
data() {
return {};
},
props: {
message: {
type: String,
default: ''
}
},
methods: {
display: function() {
alert(this.message);
}
},
};
</script>
I want to import it into an HTML file using something like this:
<script type="text/javascript" src="/components/my-component.min.js"></script>
Then, I would like to be able to just use the component in my HTML file like this:
<my-component message="hello"></my-component>
Is this possible? If so, how? Everything that I see uses web pack and a bunch of other stuff. I have a working component. I just can't figure out how to make it easily deployable.
I created a gulpfile to help with this. This looks like this:
gulpfile.js
var gulp = require('gulp');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var webpack = require('webpack-stream');
gulp.task('default', ['build']);
gulp.task('build', [], function() {
return gulp.src('./src/my-component')
.pipe(webpack(require('./webpack.config.js')))
.pipe(concat('my-component.min.js'))
.pipe(gulp.dest('./deploy'))
;
});
When I run the build gulp task, I receive a message that says:
webpack-stream - No files given; aborting compilation
The confusing part is, I have some unit tests that successfully work. I'm running those tests via this command:
nyc mocha-webpack --webpack-config ./webpack.config.js test --recursive --require test/.setup
What am I doing wrong? How do I package up my component so that I can import it into other apps?
If you don't want to use any bundle - a full webpack bundle (please reconsider this decision if you are working on a big project) nor browserify (see vueify)... then you may use this package to compile single file component into single js file, with gulp:
https://www.npmjs.com/package/gulp-vueify2
I must mention that I am the author of this module.

What is the proper folder structure for a polymer app?

I've got an app with several custom elements in it, and I'm writing tests, and I'm not sure how the directories are supposed to be set up for tests to work.
Is it something like:
myApp
myApp/bower_components
myApp/test
myApp/test/myApp
myApp/test/myElement1
myApp/test/myElement2
myApp/test/myElement3
myApp/src
myApp/src/myApp
myApp/src/myElement1
myApp/src/myElement2
myApp/src/myElement3
myApp/demo
Or does each element get a test/ subfolder? Like
myApp/src/myElement1/test
myApp/src/myElement2/test
myApp/src/myElement3/test
According to the docs here each element has a test folder that can be accessed via the browser when you use polymer serve like so localhost:8080/components/my-el/test/my-el_test.html
The test should be in their own folder separated from the app main directory to facilitate the Polymer CLI's build process. (Making your app production ready.)
Recommended Structure:
myApp/test/myElement1
myApp/src/myElement1
Here’s an example polymer.json file from the Shop app: ((No Test Folder))
polymer.json
{
"entrypoint": "index.html",
"shell": "src/shop-app.html",
"fragments": [
"src/shop-list.html",
"src/shop-detail.html",
"src/shop-cart.html",
"src/shop-checkout.html",
"src/lazy-resources.html"
],
"sources": [
"src/**/*",
"data/**/*",
"images/**/*",
"bower.json"
],
"extraDependencies": [
"manifest.json",
"bower_components/webcomponentsjs/webcomponents-lite.js"
],
"lint": {
"rules": ["polymer-2-hybrid"]
}
}

Categories

Resources