The ultimate Fabric, Power BI, SQL, and AI community-led learning event. Save €200 with code FABCOMM.
Get registeredCompete to become Power BI Data Viz World Champion! First round ends August 18th. Get started.
I'm trying to develop a CesiumJS custom visual, but I can't even get it to display the globe.
Every time I start it I get multiple CORS errors:
It seems like it tries to load some assets and create some workers, but app.powerbi.com doesn't allow it. A lot of the different error messages follow this pattern:
"Access to XMLHttpRequest at <some CesiumJS file> from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource"
I modified my webpack.config.js following all the steps in here and it looks like this now:
const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const config = require("../config.json");
const TerserPlugin = require("terser-webpack-plugin");
const webpack = require('webpack');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const cesiumSource = 'node_modules/cesium/Source';
const cesiumWorkers = '../Build/Cesium/Workers';
module.exports = {
entry: {
'visual.js': ['./src/visual.ts']
},
devtool: 'source-map',
mode: "production",
optimization: {
minimizer: [
new TerserPlugin({
cache: true,
parallel: true,
sourceMap: true,
terserOptions: {}
})
],
minimize: false,
concatenateModules: false
},
performance: {
maxEntrypointSize: 1024000,
maxAssetSize: 1024000,
hints: false
},
module: {
rules: [
{
parser: {
amd: false
}
},
{
test: /\.json$/,
loader: require.resolve('json-loader'),
type: "javascript/auto"
},
{
test: /(\.less)|(\.css)$/,
use: [
{
loader: MiniCssExtractPlugin.loader
},
{
loader: require.resolve('css-loader')
},
{
loader: require.resolve('less-loader'),
options: {
paths: [path.resolve(__dirname, "..", 'node_modules')]
}
}
]
},
{
test: /\.(woff|ttf|ico|woff2|jpg|jpeg|png|webp|gif|svg|eot)$/i,
use: [
{
loader: require.resolve('base64-inline-loader')
}
]
}
],
unknownContextCritical: false
},
externals: {
"powerbi-visuals-api": 'null',
"fakeDefine": 'false',
"corePowerbiObject": "Function('return this.powerbi')()",
"realWindow": "Function('return this')()"
},
resolve: {
extensions: ['.tsx', '.ts', '.jsx', '.js', '.css'],
},
output: {
path: null,
publicPath: 'assets',
filename: "[name]",
sourcePrefix: ''
},
amd: {
toUrlUndefined: true
},
node: {
fs: 'empty'
},
devServer: {
disableHostCheck: true,
contentBase: null,
compress: true,
port: 8080,
hot: false,
inline: false,
https: true,
headers: {
"access-control-allow-origin": "*",
"cache-control": "public, max-age=0"
}
},
plugins: [
new MiniCssExtractPlugin({
filename: config.build.css,
chunkFilename: "[id].css"
}),
new CopyWebpackPlugin([ { from: path.join(cesiumSource, cesiumWorkers), to: 'Workers' } ]),
new CopyWebpackPlugin([ { from: path.join(cesiumSource, 'Assets'), to: 'Assets' } ]),
new CopyWebpackPlugin([ { from: path.join(cesiumSource, 'Widgets'), to: 'Widgets' } ]),
new webpack.DefinePlugin({
CESIUM_BASE_URL: JSON.stringify('')
})
]
};
My visual.ts looks like this:
"use strict";
import "core-js/stable";
import "./../style/visual.less";
import powerbi from "powerbi-visuals-api";
import VisualConstructorOptions = powerbi.extensibility.visual.VisualConstructorOptions;
import VisualUpdateOptions = powerbi.extensibility.visual.VisualUpdateOptions;
import IVisual = powerbi.extensibility.visual.IVisual;
import EnumerateVisualObjectInstancesOptions = powerbi.EnumerateVisualObjectInstancesOptions;
import VisualObjectInstance = powerbi.VisualObjectInstance;
import DataView = powerbi.DataView;
import VisualObjectInstanceEnumerationObject = powerbi.VisualObjectInstanceEnumerationObject;
import { VisualSettings } from "./settings";
import { Viewer, Ion } from 'cesium';
import "cesium/Build/Cesium/Widgets/widgets.css";
export class Visual implements IVisual {
private target: HTMLElement;
private container: HTMLDivElement;
private settings: VisualSettings;
constructor(options: VisualConstructorOptions) {
this.target = options.element;
}
public update(options: VisualUpdateOptions) {
let target = this.target;
let container = this.container;
let settings = this.settings;
settings = Visual.parseSettings(options && options.dataViews && options.dataViews[0]);
container = document.createElement("div");
container.id = "cesiumContainer";
target.appendChild(container);
Ion.defaultAccessToken = '<myAccessToken>';
var viewer = new Viewer('cesiumContainer');
}
private static parseSettings(dataView: DataView): VisualSettings {
return <VisualSettings>VisualSettings.parse(dataView);
}
public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstance[] | VisualObjectInstanceEnumerationObject {
return VisualSettings.enumerateObjectInstances(this.settings || VisualSettings.getDefault(), options);
}
}
Does anyone know a solution for this?
Thanks in advance!
Hi @Anonymous,
I'm not sure if I can solve this 100% for you, but might be able to provide some clarification or further ideas. I've previously attempted to use workers in a custom visual and it's... tricky.
CORS errors in a visual are typically caused by the fact that the visual is hosted in a sandboxed iframe with allow-scripts as the only permission, which means that the domain has been removed from the visual's hosting iframe. So if you need to load remote dependencies and the remote server does not allow requests from a null origin, then there's not much you can do here, unless CesiumJS can relax this restriction from their end.
Regarding Webpack customisation, I can't tell from the supplied if you're using powerbi-visuals-webpack-plugin or not in your project. If not, then trying to supply an overridden webpack configuration typically doesn't work as the SDK tools will always use the one local to the installed powerbi-visuals-tools package.
If you have done this, it might be better to contact pbicvsupport@microsoft.com with further questions and your code, and the team may be able to provide you with targeted help on this one (they typically don't look at the forums, unfortunately 😞 ). If you do get a resolution back under this channel, I'd love to know how you get on with this one - CesiumJS looks pretty cool!
Regards,
Daniel
Proud to be a Super User!
On how to ask a technical question, if you really want an answer (courtesy of SQLBI)
User | Count |
---|---|
5 | |
3 | |
2 | |
2 | |
1 |
User | Count |
---|---|
11 | |
7 | |
4 | |
4 | |
4 |