is this possible to integrate Zoom chart with angular 2need basic idea is anyone done this before , didn't find any thread related to this on Internet that's why i asked here, any clue ?
1. Description based on angular-seed application
For Angular2 - here are step by step instructions on how to get
ZoomCharts running within the angular-seed application. Note that they
only describe the steps to get a sample running within the seed
application, not the steps required to build fully functional
component.
1. Copy zoomcharts.d.ts file into /tools/manual_typings/project/
folder.
2. Modify the zoomcharts.d.ts file to support CommonJS/SystemJS
module system by adding at the top of it these lines:
declare module "ZoomCharts" {
export = ZoomCharts; }
3. In the tools\project.config.ts file add this line into the
constructor (of course, using CDN is optional) to register the library
with SystemJS loader:
this.addPackagesBundles([{ name: "ZoomCharts", path:
"https://cdn.zoomcharts-cloud.com/1/latest/zoomcharts.js" }]);
4. Create a new component for the chart, for example,
/src/client/app/home/zc-pie-chart.component.ts
``` ///
import { Component, OnInit, ViewChild, AfterViewInit, ElementRef }
from '#angular/core'; import { PieChart } from "ZoomCharts";
#Component({
moduleId: module.id,
selector: "zc-pie-chart",
template: "PieChart is being initialized..." }) export class ZcPieChart implements AfterViewInit {
#ViewChild("container")
private container: ElementRef;
ngAfterViewInit() {
var x = new PieChart({
container: this.container.nativeElement,
assetsUrlBase: System.paths["ZoomCharts"] + "/../assets/",
data: [{
url: "https://zoomcharts.com/dvsl/data/pie-chart/browsers.json",
}]
});
} } ```
5. Register the component in the module (in this sample case,
home.module.ts):
``` import { ZcPieChart } from './zc-pie-chart.component';
.. declarations: [..other components.., ZcPieChart], .. ```
6. Add it to the view, for example, home.component.html:
<zc-pie-chart></zc-pie-chart>
2. Integration with Webpack
Note: I tested this with Webpack 2.2.1.
With Webpack you can use simple import ZoomCharts from
'./zoomcharts/zoomcharts.js'; and it works fine - including bundling
of the zoomcharts.js code.
Though in such case ZoomCharts will now load dependencies such as
moment.js by itself even if they are already included in the webpack
bundle. To enable loading moment.js from the bundle, I used this
webpack.config.js file (and using the
imports-loader
plugin):
```js var path = require('path');
module.exports = {
entry: './index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname)
},
resolve: {
alias: {
"moment": path.resolve(__dirname, "zoomcharts", "assets", "moment.js"),
"moment-timezone": path.resolve(__dirname, "zoomcharts", "assets", "moment-tz.js"),
"zoomcharts": path.resolve(__dirname, "zoomcharts", "zoomcharts.js"),
}
},
module: {
rules: [
{
test: path.resolve(__dirname, "zoomcharts", "zoomcharts.js"),
loader: {
loader: "imports-loader",
options: {
"moment": "moment",
"momentTimezone": "moment-timezone",
// workaround that sets window.moment as required by zoomcharts.js
"_": ">window.moment=moment;"
}
}
}
],
} }; ```
first install zoomchart dependency
npm install --save #dvsl/zoomcharts
Html
<script src="https://cdn.zoomcharts-cloud.com/1/latest/zoomcharts.js"></script>
<div id='demo' style='width:100%; height:300px;'></div>
in ts file create a method
import * as zc from '#dvsl/zoomcharts';
import { WindowRef } from './../../WindowRef';
import { Component, OnInit} from '#angular/core';
export class ZoomChartImplementation implements OnInit{
private zc: any = zc;
constructor(private winRef: WindowRef){
winRef.nativeWindow.ZoomChartsLicense = 'INSERT YOUR ZOOM CHART LICENSE HERE';
winRef.nativeWindow.ZoomChartsLicenseKey ='INSERT YOUR ZOOM CHART LICENSE KEY HERE';
}
loadZoomChart(){
const PieChart = this.zc.PieChart;
const t = new PieChart({
container: document.getElementById('demo'),
area: { height: 350 },
data: {
preloaded: {
subvalues: [
{
id: 'foo', value: 100, subvalues: [
{ id: 'foo-1', value: 50, style: { expandable: false } },
{ id: 'foo-2', value: 50, style: { expandable: false } }
]
},
{ id: 'bar', value: 50, style: { expandable: false } },
{ id: 'baz', value: 30, style: { expandable: false } }
]
}
}
});
}
}
you can use any chart instead of pie-chart in my example
this.zc.ANY_CHART
Related
So I'm using vite to build my Vue 3 application for a legacy website which still uses jQuery and a few other JS frameworks.
I'm using the esm bundler as I would still like to boot it up and use it with slotted components.
<div id="app">
<vue-component-name></vue-component-name>
</div>
And it works perfectly. But when jQuery is used on the page, no where near my components it seems the esm bundled version of Vue has set a global variable named $ which breaks jQuery.
Has anyone had this issue or know of a way to fix it?
import { defineConfig } from 'vite';
import type { UserConfig as VitestUserConfigInterface } from 'vitest/config';
import svgLoader from 'vite-svg-loader';
import vue from '#vitejs/plugin-vue';
import path from 'path';
const vitestConfig : VitestUserConfigInterface = {
test: {
globals: true,
include: ['./tests/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
},
};
export default defineConfig({
test: vitestConfig.test,
plugins: [vue(), svgLoader()],
base: '/',
resolve: {
alias: {
vue: 'vue/dist/vue.esm-bundler.js',
'#': path.resolve(__dirname, '/src'),
},
},
build: {
outDir: '../wwwroot/dist',
emptyOutDir: true,
manifest: true,
rollupOptions: {
input: {
main: './src/main.ts',
},
output: {
entryFileNames: 'assets/js/[name].js',
chunkFileNames: 'assets/js/[name].js',
assetFileNames: ({ name }) => {
if (/\.(gif|jpe?g|png|svg)$/.test(name ?? '')) {
return 'assets/images/[name][extname]';
}
if ((name ?? '').endsWith('.css')) {
return 'assets/css/[name][extname]';
}
return 'assets/[name][extname]';
},
globals: {
vue: 'Vue',
},
},
},
},
server: {
hmr: {
protocol: 'ws',
},
},
});
EDIT:
More information, I've tracked this down to using
#input="handleInput($event.target, index)"
This right here breaks existing jQuery. Still no idea how to get around it
For anyone interested, How to wrap Vite build in IIFE and still have all the dependencies bundled into a single file?
Webpack configuration is a part of Vue CLI setup (can be checked with vue inspect). This is a relevant part of it:
entry: {
foo: [
'.../src/foo.js'
],
barWidget: [
'.../src/barWidget.js'
],
},
optimization: {
splitChunks: {
cacheGroups: {
vendors: {
name: 'chunk-vendors',
test: /[\\/]node_modules[\\/]/,
priority: -10,
chunks: 'initial'
},
common: {
name: 'chunk-common',
minChunks: 2,
priority: -20,
chunks: 'initial',
reuseExistingChunk: true
}
}
},
...
And HTML output is:
<script type="text/javascript" src="/assets/js/chunk-vendors.[HASH].js"></script>
<script type="text/javascript" src="/assets/js/foo.[HASH].js"></script>
and
<script type="text/javascript" src="/assets/js/chunk-vendors.[HASH].js"></script>
<script type="text/javascript" src="/assets/js/barWidget.[HASH].js"></script>
There's no problem for foo to have as many script tags as needed, but barWidget is widget entry point that is supposed to be loaded at once with no initial chunk dependencies. My intention is to make barWidget be loaded with a single line of code (hash will likely be disabled for this purpose):
<script type="text/javascript" src="/assets/js/barWidget.js"></script>
But in its current state it fails to load if chunk-vendors is omitted.
I'd prefer to keep vendors and common chunks as they are because they are splitted in a reasonable way and can be reused on client side between entry points, but I need barWidget to auto-load a chunk it depends on. A less preferable way would be to disable chunks but for barWidget only, chunk splitting in other entry points should remain unchanged.
A way to reproduce it is basically a new Vue CLI project with 2 entry points added, or any Webpack project with similarly configured splitting.
Here is the project (listed for completeness):
package.json
{
"name": "foobar",
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build"
},
"dependencies": {
"core-js": "^3.6.5",
"vue": "^3.0.0"
},
"devDependencies": {
"#vue/cli-plugin-babel": "~4.5.0",
"#vue/cli-service": "~4.5.0",
"#vue/compiler-sfc": "^3.0.0"
}
}
vue.config.js
module.exports = {
pages: {
foo: {
entry: 'src/foo.js',
template: 'public/foo.html',
filename: 'foo.html'
},
barWidget: {
entry: 'src/barWidget.js',
template: 'public/barWidget.html',
filename: 'barWidget.html'
},
},
};
public/foo.html
public/barWidget.html
<!DOCTYPE html>
<html>
<body>
<div id="app"></div>
</body>
</html>
src/foo.js
import { createApp } from 'vue'
import Foo from './Foo.vue'
createApp(Foo).mount('#app')
Foo.vue
<template>
<HelloWorld msg="Foo"/>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
components: {
HelloWorld
}
}
</script>
src/barWidget.js
import { createApp } from 'vue'
import BarWidget from './BarWidget.vue'
createApp(BarWidget).mount('#app')
BarWidget.vue
<template>
<HelloWorld msg="Bar widget"/>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
components: {
HelloWorld
}
}
</script>
Can barWidget be forced to automatically load chunk-vendors.[HASH].js by means of Webpack, without loading it explicitly in the place where barWidget.[HASH].js is being used?
Can barWidget entry point be forced to not use other initial chunks (chunk-vendors, etc) and output self-sufficient barWidget.js bundle, without affecting the way splitting works in other entry points?
Are there other options for the described scenario?
I think that what you want is what is described in this webpack issue reply
the reply uses a function to exclude the dependencies of a specific entrypoint from being included in a chunk:
optimization: {
splitChunks: {
cacheGroups: {
vendors: {
// ... your current config, just change the chunks property
// Exclude pre-main dependencies going into vendors, as doing so
// will result in webpack only loading pre-main once vendors loaded.
// But pre-main is the one loading vendors.
// Currently undocument feature: https://github.com/webpack/webpack/pull/6791
chunks: chunk => chunk.name !== "barWidget"
}
}
}
},
to do this with vue should be just a matter of changing the webpack config in the vue.config.js file like this:
module.exports = {
configureWebpack: config => {
config.optimization.splitChunks.cacheGroups.vendors.chunks =
chunk => chunk.name !== "barWidget";
}
}
I haven't tried this but I think it should work as is or with some minimal tweaks
You can use a function to filter the chunks. See this Webpack issue
vue.config.js
module.exports = {
pages: {
foo: {
entry: 'src/foo.js',
template: 'public/foo.html',
filename: 'foo.html'
},
barWidget: {
entry: 'src/barWidget.js',
template: 'public/barWidget.html',
filename: 'barWidget.html',
chunks: ['barWidget']
},
},
chainWebpack: config => {
if (process.env.NODE_ENV !== 'test') {
config.optimization.splitChunks({
cacheGroups: {
defaultVendors: {
name: `chunk-vendors`,
test: /[\\/]node_modules[\\/]/,
priority: -10,
chunks: chunk => chunk.name !== "barWidget"
},
common: {
name: `chunk-common`,
minChunks: 2,
priority: -20,
chunks: 'initial',
reuseExistingChunk: true
}
}
})
}
}
}
Note the pages.barWidget.chunks - it is needed because otherwise HtmlWebpackPlugin includes vendors chunk into barWidget.html even it is not needed at all...
Result:
I am trying to use a component library that I created to reuse in other projects. In it I used loadable-components with webpack and code splitting.
But, when importing into a Next.js project, errors are returned, showing that you cannot import the component from that library.
I have two projects:
Project A = Component library
Project B = Will import Project A
Project B that imported the library (Project A):
(node:20271) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'SomeComponent' of undefined
Config of the imported library (Project A):
webpack.build.config.js
module.exports = {
...
entry: {
[packageName]: './src/index.js'
},
target: 'web',
output: {
chunkFilename: '[chunkhash].chunk.js',
library: packageName,
libraryTarget: 'commonjs2',
globalObject: 'this'
},
externals: nodeExternals(),
optimization: {
minimize: true,
usedExports: true,
splitChunks: {
chunks: 'all',
},
},
plugins: [
new LoadablePlugin()
],
...
}
src/index.js
import styled, { ServerStyleSheet, createGlobalStyle } from 'styled-components';
export * from '#components';
export * from '#style';
export { default as Icons } from '#assets/icons';
export { styled, ServerStyleSheet, createGlobalStyle };
Above, only the #components folder has loadable-components
.babelrc
{
"plugins": [
"styled-components",
[
"#babel/plugin-proposal-pipeline-operator",
{
"proposal": "minimal"
}
],
[
"#babel/plugin-proposal-optional-chaining",
{
"loose": false
}
],
[
"#babel/plugin-proposal-class-properties",
{
"loose": true
}
],
"#loadable/babel-plugin"
]
}
In the Project B, I only import this library with the generated chunks.
But, the same error is always shown, regardless of whether the component is loaded on demand or not.
What am I doing wrong? Any suggestion?
Thanks!
I'm new to Webpack, so my terms may not be entirely correct. What I'm trying to do is build a custom Phaser module first, then import it into the other entry point, which depends on it.
EDIT: I've tried using SplitChunks, Dynamic Imports, and aliases. But no avail. Is there anyway to accomplish this via plugins or methodology?
From webpack.config.js:
entry: {
'phaser.min': './phaser-builder.js',
game: './src/index.js'
},
resolve: {
alias: {
'eventemitter3': path.resolve(__dirname, './node_modules/eventemitter3')
},
modules: [ 'node_modules/phaser/src', 'node_modules' ]
},
output: {
path: path.resolve(__dirname, 'build'),
filename: '[name].js',
library: 'Phaser',
libraryTarget: 'umd',
sourceMapFilename: '[file].map',
devtoolModuleFilenameTemplate: 'webpack:///[resource-path]',
devtoolFallbackModuleFilenameTemplate: 'webpack:///[resource-path]?[hash]',
umdNamedDefine: true
},
Contents of phaser-builder.js:
require('polyfills');
var CONST = require('const');
var Extend = require('utils/object/Extend');
var Phaser = {
... code ...
};
Phaser = Extend(false, Phaser, CONST);
module.exports = Phaser;
global.Phaser = Phaser;
index.js (second entry point) needs the 'Phaser' object from phaser.min.js that is created from ./phaser-builder.js (first entry point) as shown below:
Contents of index.js:
//import 'phaser'; //this works but it's not the custom build from entry point one.
import { Phaser } from '../build/phaser.min';
import { TestScene } from './scenes/TestScene';
const gameConfig = {
width: 680,
height: 400,
scene: TestScene
};
new Phaser.Game(gameConfig);
Contents of TestScene.js: (imported in index.js)
export class TestScene extends Phaser.Scene {
preload() {
this.load.image('logo', 'assets/sprites/logo.png');
}
create() {
this.add.text(100, 100, 'Working...', { fill: '#0f0' });
this.add.image(100, 200, 'logo');
}
}
As commented in index.js above, if I simply use import 'phaser'; (which is pulling from node_modules I presume?) Everything works fine. But that is the full phaser lib, which I don't want. I want to import the custom build I created in entry point one, that exists in /build/phaser.min.js
If I try importing from /build/phaser.min.js I get this error:
"TypeError: Super expression must either be null or a function"
Which from my understanding is basically saying that Phaser object/module is undefined, so TestScene is not extending Phaser.Scene as expected.
With webpack I add specific build of phaser in the followed way, I hope this is what you are looking for or at least will give you any idea how could we do with webpack
thank you.
UPDATE: My lead was able to solve this probllem. Please see answer below, and I hope that this helps at least some people
The following code throws the exception, but note that when I don't import/use d3-selection, then the whole app runs without errors. As soon as I import select from 'd3-selection', I get the error that I mentioned in the title.
import { Component, ElementRef, ViewChild } from '#angular/core';
import { select } from 'd3-selection';
#Component({
selector: 'pie',
template: `<ng-content></ng-content>`
})
export class PieChartComponent {
#ViewChild('containerPieChart')
private element: ElementRef;
constructor() {
select(this.element.nativeElement);
}
}
I checked the possible dupes in here, and none applied to me, so here I am.
The code that is bundled/imported from TypeScript is:
function(name) {
return select(creator(name).call(document.documentElement));
}
I know this is invalid in JS, because functions must have names, or be IIFEs in order to omit the name. Or object declarations. So, why is d3 transpiling into invalid JS?
EDIT: I am using rollup.config.dev.js with the following code:
import bundles from './bundles.json';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import scss from 'rollup-plugin-scss';
import sourcemaps from 'rollup-plugin-sourcemaps';
const
DEV_DIRECTORY = `dev`
, MODULE_NAME_PATH = 'AST.app'
;
function createDevBundle(bundle) {
let bundleDirectory = `${DEV_DIRECTORY}/${bundle.name}`;
return {
input: bundle.input,
name: `${MODULE_NAME_PATH}.${bundle.name}`,
output: {
file: `${bundleDirectory}/${bundle.name}.js`,
format: 'umd'
},
exports: 'default',
plugins: [
resolve({
jsnext: true,
module: true
}),
commonjs(),
sourcemaps(),
scss({
output: `${bundleDirectory}/${bundle.name}.css`,
includePaths: ['../global/scss/base']
})
],
onwarn: function(warning) {
// Recommended warning suppression by angular team.
if (warning.code === 'THIS_IS_UNDEFINED') {
return;
}
// eslint-disable-next-line no-console
console.error(warning.message);
},
treeshake: false,
sourcemap: true
};
}
export default bundles.map(createDevBundle);
I wasn't able to, but my lead was able to fix this problem. The following packages were updated in the package.json:
"rollup-plugin-commonjs": "8.3.0",
"rollup-plugin-execute": "1.0.0",
"rollup-plugin-node-resolve": "3.0.3",
"rollup-plugin-sourcemaps": "0.4.2",
"rollup-plugin-uglify": "3.0.0"
An update was made to rollup.config.js and rollup.config.dev.js. The sections of name, exports, and sourcemap were moved over to the output section. See below:
function createDevBundle(bundle) {
let bundleDirectory = `${DEV_DIRECTORY}/${bundle.name}`;
return {
input: bundle.input,
output: {
file: `${bundleDirectory}/${bundle.name}.js`,
name: `${MODULE_NAME_PATH}.${bundle.name}`,
exports: 'default',
sourcemap: true,
format: 'umd'
}
... [omitted for brevity]