JSPM

  • Created
  • Published
  • Downloads 3051
  • Score
    100M100P100Q129603F
  • License MIT

PowerBI Custom Visuals webpack plugin

Package Exports

  • powerbi-visuals-webpack-plugin

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (powerbi-visuals-webpack-plugin) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

powerbi-visuals-webpack-plugin

npm version npm

This plugin allows developing custom visuals by using webpack to build a visual package.

Provides following functionality:

  • Creates assets for developer server
  • Creates *.pbiviz package.

How to use the plugin

Plugin options

Plugin config description

  var defaultOptions = {
      visual: {
        name: "Visual name",
        displayName: "Visual name for displaying in visuals panel",
        guid: `Unique GUID for the visual (generated by plugin)`,
        visualClassName: "Visual class name, it is used by visual plugin to create instance of the visual",
        version: "Visual version",
        description: "Visual description",
        supportUrl: "URL for support"
    },
    author: "Author of the visual",
    apiVersion: "API version",
    stringResourcesPath: [
      "Paths to localization files"
    ],
    capabilities: {
        // Visual capabilities
    },
    iconImage: "Icon file as base64 string",
    devMode: "development mode",
    packageOutPath: "location to create *.pbiviz file",
    cssStyles: "styles",
    generateResources: "it is used --resources flag in pbiviz tools",
    generatePbiviz: "it is used by --no-pbiviz flag in pbiviz tools"
  };

Webpack configuration

The sample of config webpack 4.

const path = require('path');
const fs = require("fs");

// werbpack plugin
const webpack = require("webpack");
console.log(require.resolve('powerbi-visuals-webpack-plugin'));
const PowerBICustomVisualsWebpackPlugin = require('powerbi-visuals-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const Visualizer = require('webpack-visualizer-plugin');
const ExtraWatchWebpackPlugin = require('extra-watch-webpack-plugin');

// api configuration
const powerbiApi = require("powerbi-visuals-api");

// visual configuration json path
const pbivizPath = "./pbiviz.json";
const pbivizFile = require(path.join(__dirname, pbivizPath));

// the visual capabilities content
const capabilitiesPath = "./capabilities.json";
const capabilitiesFile = require(path.join(__dirname, capabilitiesPath));

const pluginLocation = './.tmp/precompile/visualPlugin.ts'; // path to visual plugin file, the file generates by the plugin

// string resources
const resourcesFolder = path.join(".","stringResources");
const localizationFolders = fs.readdirSync(resourcesFolder);

// babel options to support IE11
let babelOptions = {
    "presets": [
        [
            require.resolve('@babel/preset-env'),
            {
                "targets": {
                    "ie": "11"
                },
                useBuiltIns: "entry",
                modules: false
            }
        ]
    ],
    sourceType: "unambiguous", // tell to babel that the project can contains different module types, not only es2015 modules
    cacheDirectory: path.join(".tmp", "babelCache") // path for chace files
};

module.exports = {
    entry: {
        "visual.js": pluginLocation
    },
    optimization: {
        concatenateModules: false,
        minimize: true // enable minimization for create *.pbiviz file less than 2 Mb, can be disabled for dev mode
    },
    devtool: 'source-map',
    mode: "development",
    module: {
        rules: [
            {
                parser: {
                    amd: false
                }
            },
            {
                test: /(\.ts)x|\.ts$/,
                include: /powerbi-visuals-|src|precompile\\visualPlugin.ts/,
                use: [
                    {
                        loader: require.resolve('babel-loader'),
                        options: babelOptions
                    },
                    {
                        loader: require.resolve('ts-loader'),
                        options: {
                            transpileOnly: false,
                            experimentalWatchApi: false
                        }
                    }
                ]
            },
            {
                test: /(\.js)x|\.js$/,
                use: [
                    {
                        loader: require.resolve('babel-loader'),
                        options: babelOptions
                    }
                ]
            },
            {
                test: /\.json$/,
                loader: require.resolve('json-loader'),
                type: "javascript/auto"
            },
            {
                test: /\.less$/,
                use: [
                    {
                        loader: MiniCssExtractPlugin.loader
                    },
                    {
                        loader: require.resolve('css-loader')
                    },
                    {
                        loader: require.resolve('less-loader'),
                        options: {
                            paths: [path.resolve(__dirname, "..", 'node_modules')]
                        }
                    }
                ]
            },
            {
                test: /\.css$/,
                use: [
                    {
                        loader: MiniCssExtractPlugin.loader
                    },
                    {
                        loader: require.resolve('css-loader')
                    }
                ]
            }
        ]
    },
    resolve: {
        extensions: ['.tsx', '.ts', '.jsx', '.js', '.css']
    },
    output: {
        path: path.join(__dirname, "/.tmp","drop"),
        publicPath: 'assets',
        filename: "[name]",
    },
    devServer: {
        disableHostCheck: true,
        contentBase: path.join(__dirname, ".tmp", "drop"), // path with assets for dev server, they are generated by webpack plugin
        compress: true,
        port: 8080, // dev server port
        hot: false,
        inline: false,
        // cert files for dev server
        https: {
            // key: path.join(__dirname, "certs","PowerBICustomVisualTest_public.key"), // for darwin, linux
            // cert: path.join(__dirname, "certs", "PowerBICustomVisualTest_public.cer"), // for darwin, linux
            pfx: fs.readFileSync(path.join(__dirname, "certs", "PowerBICustomVisualTest_public.pfx")), // for windows
            passphrase: "5031595470751755"
        },
        headers: {
            "access-control-allow-origin": "*",
            "cache-control": "public, max-age=0"
        },
    },
    externals: {
        "powerbi-visuals-api": 'null',
        "fakeDefine": 'false',
        "corePowerbiObject": "Function('return this.powerbi')()",
        "realWindow": "Function('return this')()"
    },
    plugins: [
        new MiniCssExtractPlugin({
            filename: "visual.css",
            chunkFilename: "[id].css"
        }),
        new Visualizer({
            filename: "webpack.statistics.dev.html"
        }),
        // visual plugin regenerates with the visual source, but it does not require relaunching dev server
        new webpack.WatchIgnorePlugin([
            path.join(__dirname, pluginLocation),
            "./.tmp/**/*.*"
        ]),
        // custom visuals plugin instance with options
        new PowerBICustomVisualsWebpackPlugin({
            ...pbivizFile,
            capabilities: capabilitiesFile,
            stringResources: localizationFolders.map(localization => path.join(
                resourcesFolder,
                localization,
                "resources.resjson"
            )),
            apiVersion: powerbiApi.version,
            capabilitiesSchema: powerbiApi.schemas.capabilities,
            pbivizSchema: powerbiApi.schemas.pbiviz,
            stringResourcesSchema: powerbiApi.schemas.stringResources,
            dependenciesSchema: powerbiApi.schemas.dependencies,
            devMode: false,
            generatePbiviz: true,
            generateResources: true,
            modules: true,
            visualSourceLocation: "../../src/visual",
            pluginLocation: pluginLocation,
            packageOutPath: path.join(__dirname, "dist")
        }),
        new ExtraWatchWebpackPlugin({
            files: [
                pbivizPath,
                capabilitiesPath
            ]
        }),
        new webpack.ProvidePlugin({
            window: 'realWindow',
            define: 'fakeDefine',
            powerbi: 'corePowerbiObject'
        }),
    ]
};

Contributing

This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.microsoft.com.

When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.