pythonflaskwebpackslickgrid

Minimum working example for Slickgrid + Webpack + Flask


I want to include slickgrid (npm install slickgrid, slickgrid.net) in my Python Flask project and I don't want to use CDN, so I'm looking at a Webpack solution.

I have been following the procedure for integrating npm packages in Flask using Webpack and as a starting point I have forked the following minimum working example https://github.com/jrybicki-jsc/flasknpm which by default works fine.

I change the file my.js to simply:

import SlickGrid from 'slickgrid';

but when I run the command npm run build (which uses webpack), I get the following error:

ERROR in ./node_modules/slickgrid/dist/esm/index.js
Module parse failed: Unexpected token (67:54)
You may need an appropriate loader to handle this file type.
|    */
|   stopPropagation() {
|     this._isPropagationStopped = !0, this.nativeEvent?.stopPropagation();
|   }
|   /**
 @ ./src/my.js 1:0-34

As a MWE I would like to get Slickgrid "Example1" working, which can be found at this link in the official slickgrid repo: example1

Anybody has some pointers on how to integrate Slickgrid with Flask through Webpack?


Solution

  • It was not a WebPack issue. Apparently Babel is required for the proper translation. I followed this answer to find my way to a solution, in particular the answer from the Babel team member khizerrehandev. I choose this because it was using the most recent version of Babel7 and works with the latest Webpack5.

    After some trial and error I came to this MWE.

    EDIT: I noticed that the original solution (still reported here below under "VERSION-0" for completeness was having issues displaying the position of the Slickgrid grid. Sometimes it would show with a "top: 32pix" (correct) and sometimes with "top: 108px" randomly as I would refresh the browser page. I later found out that this is because the slick-alpine-theme.css file was loaded directly into the index.html and not bundled into the bundle.js. In "VERSION-1" I show the changes to bundle the css with webpack and avoid this issue.


    VERSION-0

    package.json

    {
      "name": "slickgrid_webpack_flask_MWE",
      "version": "1.0.0",
      "description": "",
      "main": "bundle.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "build": "webpack --config webpack.config.js"
      },
      "keywords": [],
      "author": "",
      "license": "ISC",
      "devDependencies": {
        "@babel/core": "^7.25.2",
        "@babel/preset-env": "^7.25.3",
        "babel-loader": "^9.1.3",
        "webpack": "^5.93.0",
        "webpack-cli": "^5.1.4"
      },
      "dependencies": {
        "slickgrid": "^5.11.0",
        "sortablejs": "^1.15.2"
      }
    }
    

    .babelrc

    {
      "presets": ["@babel/preset-env"]
    }
    

    webpack.config.js

    const path = require('path');
    
    module.exports = {
      entry: './static/my.js',
      output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'static')
      },
      module: {
          rules: [{
                  test: /\.(js)$/,
                  exclude: /node_modules/,
                  use: {
                      loader: 'babel-loader'
                  }
              }
          ]
      },
    };
    

    app.py

    from flask import Flask, render_template
    
    app = Flask(__name__)
    
    @app.route('/')
    def main():
        return render_template('index.html')
    
    if __name__=="__main__":
        app.run(debug=True)
    

    index.html

    Notice that here I hard copied slick-alpine-theme.css from the node_modules directory to my static folder. In fact I don't know how to load the css directly from node_modules or somehow include it in the bundle. Also notice the type="module" when loading the bundle.

    <html lang="en">
    <head>
        <link rel="stylesheet" href="{{ url_for('static', filename='slick-alpine-theme.css') }}" type="text/css"/>
        <script type="module" src="{{ url_for('static', filename='bundle.js') }}"></script>
        <title>slickgrid webpack flask MWE</title>
    </head>
    <body>
    <div id="myGrid" class="slick-container" style="width:600px;height:500px;"></div>
    </body>
    </html>
    

    my.js

    This is the same code as example1-simple.html with slight modifications

    import { SlickGrid } from 'slickgrid';
    import Sortable from 'sortablejs';
    
    var grid;
    var columns = [
    {id: "title", name: "Title", field: "title"},
    {id: "duration", name: "Duration", field: "duration"},
    {id: "%", name: "% Complete", field: "percentComplete", width: 90 },
    {id: "start", name: "Start", field: "start"},
    {id: "finish", name: "Finish", field: "finish"},
    {id: "effort-driven", name: "Effort Driven", field: "effortDriven", width: 90 }
    ];
    
    var options = {
    enableCellNavigation: true,
    enableColumnReorder: false
    };
    
    var data = [];
    for (var i = 0; i < 500; i++) {
        data[i] = {
          title: "Task " + i,
          duration: "5 days",
          percentComplete: Math.round(Math.random() * 100),
          start: "01/01/2009",
          finish: "01/05/2009",
          effortDriven: (i % 5 == 0)
        };
    }
    
    
    grid = new SlickGrid("#myGrid", data, columns, options);
    

    Now for the bundle.js creation with the command npm run build and of course launch flask.

    One thing that is left to find out for me is if I included sortablejs correctly.


    VERSION-1

    To solve the issue mentioned at the beginning we need to bundle the css file with bundle.js using webpack. This requires three changes:

    index.html

    Remove the line

    <link rel="stylesheet" href="{{ url_for('static', filename='slick-alpine-theme.css') }}" type="text/css"/>
    

    my.js

    Add the line

    import "./slick-alpine-theme.css"
    

    webpack.config.js

    Add the rule

    {
        test: /\.css$/,
        use: [
            'style-loader',
            'css-loader']
    }
    

    The last steps are to install the npm packages

    npm install --save-dev style-loader css-loader
    

    and rebuild `npm run build'