lit / lit-element

LEGACY REPO. This repository is for maintenance of the legacy LitElement library. The LitElement base class is now part of the Lit library, which is developed in the lit monorepo.
https://lit-element.polymer-project.org
BSD 3-Clause "New" or "Revised" License
4.49k stars 319 forks source link

Web Components not working in IE11 with Webpack and Babel #978

Closed fregiese closed 4 years ago

fregiese commented 4 years ago

Problem

Currently IE11 ist not rendering our Web Components that we build with Lit-Elements. We don't get any errors in the IE11 Console, but Web Components are still not showing. We only have these Problems with IE11. Every other browser is showing all of our Web Components with no problems at all.

Structure

We load the polyfills in the head. After that we load our .js with all of our web components. All files are found and loaded in IE11.

<link rel="stylesheet" href="./style.css">
<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-bundle.js"></script>
<script src="./index.js"></script> // some css styles and 'intersection-observer' polyfill are here.
<script src="./components.js"></script> // all our components are here

We also normally have a vendor.js with bootstrap and jquery and so on, but we currently don't load the file to isolate the problem.

babel.config.js

module.exports = {
    presets: [
        [
            '@babel/preset-env',
        ],
    ],
    plugins: [
        [
            '@babel/plugin-proposal-decorators',
            {
                legacy: true,
            },
        ],
        '@babel/plugin-proposal-class-properties',
        [
            '@babel/plugin-transform-runtime',
            {
                regenerator: true,
            },
        ],
    ],
};

webpack.config.js

const path = require('path');
const WebpackPwaManifest = require('webpack-pwa-manifest');
const StylelintPlugin = require('stylelint-webpack-plugin');
const SVGSpritemapPlugin = require('svg-spritemap-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const { resolve } = require('./webpack-utils/webpack.resolve');

module.exports = {
    context: process.cwd(),
    entry: {
        index: './src/js/index.js',
        components: './src/js/components',
        vendor: ['bootstrap', 'jquery', 'mediaelement/full', 'mediaelement/build/lang/de'], // maybe removed later, if web components load them async
    },
    output: {
        filename: '[name].js',
        path: path.resolve(__dirname, 'dist/current/public'),
    },
    watchOptions: {
        ignored: /node_modules/,
    },
    resolve,
    module: {
        rules: [
            {
                test: /style.scss/,
                use: [
                    MiniCssExtractPlugin.loader,
                    {
                        loader: 'css-loader',
                        options: {
                            importLoaders: 1,
                        },
                    },
                    {
                        loader: 'postcss-loader',
                    },
                ],
            },
            {
                test: /vendor.scss/,
                use: [
                    'style-loader',
                    {
                        loader: 'css-loader',
                        options: {
                            importLoaders: 1,
                        },
                    },
                    {
                        loader: 'sass-loader',
                    },
                ],
            },
            {
                enforce: 'pre',
                test: /\.js$/,
                exclude: /node_modules/,
                loader: 'eslint-loader',
            },
            {
                test: /\.js$/,
                exclude: /node_modules\/(?!(lit-element|lit-html)\/).*/,
                loader: 'babel-loader',
            },
            {
                test: /\.(woff|woff2|eot|ttf|otf)$/,
                use: [
                    {
                        loader: 'file-loader',
                        options: {
                            name: 'fonts/[name].[ext]',
                            publicPath: './',
                        },
                    },
                ],
            },
            {
                test: /\.(jpe?g|png|gif|svg)$/,
                use: [
                    {
                        loader: 'file-loader',
                        options: {
                            name: 'content/[name].[ext]',
                        },
                    },
                ],
            },
        ],
    },
    plugins: [
        new StylelintPlugin(),
        new WebpackPwaManifest({
            name: 'INQA Webseite',
            short_name: 'INQA',
            description: 'Die Webseite von BMAS-INQA',
            background_color: '#ffffff',
            crossorigin: 'use-credentials', // can be null, use-credentials or anonymous
            icons: [
                {
                    src: path.resolve('src/img/icons/favicon.png'),
                    sizes: [96, 128, 192, 256, 384, 512], // multiple sizes
                },
            ],
            fingerprints: false,
        }),
        new SVGSpritemapPlugin('src/img/sprite/**/*.svg', {
            sprite: {
                generate: {
                    title: false,
                },
            },
        }),
        new MiniCssExtractPlugin({
            filename: 'style.css',
        }),
    ],
};

package.json

{
  "name": "test",
  "version": "1.0.0",
  "description": "website",
  "author": "test@gmx.de",
  "private": true,
  "scripts": {
    "start": "concurrently \"npm run build:watch\" \"npm run storybook\"",
    "build:dev": "webpack --mode development",
    "build:prod": "webpack --mode production",
    "build:watch": "webpack --watch --mode development",
    "check": "npm run lint && npm run budget",
    "lint": "npm run lint:css:fix && npm run lint:js:fix",
    "lint:css": "stylelint \"**/*.scss\"",
    "lint:css:fix": "stylelint \"**/*.scss\" --fix",
    "lint:js": "eslint .",
    "lint:js:fix": "eslint --fix .",
    "storybook": "start-storybook -p 3000 -s ./dist/current/public ",
    "storybook:build": "npm run build:prod && build-storybook -s ./dist/current/public -o ./dist/current/storybook",
    "release": "npm run storybook:build",
    "doc": "doctoc README.md",
    "budget": "bundlesize"
  },
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged && npm run build:prod && npm run budget"
    }
  },
  "lint-staged": {
    "*.js": "npx eslint --fix",
    "*.scss": "npx stylelint --fix"
  },
  "devDependencies": {
    "@babel/core": "^7.9.0",
    "@babel/plugin-proposal-class-properties": "^7.8.3",
    "@babel/plugin-proposal-decorators": "^7.8.3",
    "@babel/preset-env": "^7.9.5",
    "@storybook/addon-a11y": "^5.3.18",
    "@storybook/addon-docs": "^5.3.18",
    "@storybook/addon-storysource": "^5.3.18",
    "@storybook/addon-viewport": "^5.3.18",
    "@storybook/addons": "^5.3.18",
    "@storybook/html": "^5.3.18",
    "@webcomponents/webcomponentsjs": "^2.4.3",
    "@whitespace/storybook-addon-html": "^1.2.1",
    "babel-eslint": "^8.2.6",
    "babel-loader": "^8.1.0",
    "bundlesize": "^0.18.0",
    "clean-webpack-plugin": "^3.0.0",
    "concurrently": "^5.1.0",
    "css-loader": "^3.5.1",
    "cssnano": "^4.1.10",
    "doctoc": "^1.4.0",
    "eslint": "^6.8.0",
    "eslint-config-airbnb-base": "^14.1.0",
    "eslint-import-resolver-webpack": "^0.12.1",
    "eslint-loader": "^4.0.0",
    "eslint-plugin-compat": "^3.5.1",
    "eslint-plugin-import": "^2.20.2",
    "husky": "^3.1.0",
    "lint-staged": "^10.1.3",
    "mini-css-extract-plugin": "^0.9.0",
    "postcss": "^7.0.27",
    "postcss-import": "^12.0.1",
    "postcss-inline-svg": "^4.1.0",
    "postcss-loader": "^3.0.0",
    "postcss-nested": "^4.2.1",
    "postcss-preset-env": "^6.7.0",
    "postcss-pxtorem": "^4.0.1",
    "postcss-scss": "^2.0.0",
    "postcss-simple-vars": "^5.0.2",
    "style-loader": "^1.1.3",
    "stylelint": "^12.0.1",
    "stylelint-config-standard": "^19.0.0",
    "stylelint-declaration-strict-value": "^1.1.8",
    "stylelint-order": "^4.0.0",
    "stylelint-webpack-plugin": "^1.2.3",
    "svg-spritemap-webpack-plugin": "^3.5.5",
    "webpack": "^4.42.1",
    "webpack-cli": "^3.3.11",
    "webpack-pwa-manifest": "^4.2.0"
  },
  "dependencies": {
    "@babel/plugin-transform-runtime": "^7.9.0",
    "@babel/runtime": "^7.9.2",
    "bootstrap": "^4.4.1",
    "core-js": "^3.6.5",
    "intersection-observer": "^0.7.0",
    "jquery": "^3.4.1",
    "lit-element": "^2.3.1",
    "lit-html": "^1.2.1",
    "mediaelement": "^4.2.16",
    "node-sass": "^4.14.0",
    "postcss-url": "^8.0.0",
    "ramda": "^0.27.0",
    "sass-loader": "^8.0.2",
    "tailwindcss": "^1.2.0"
  },
  "keywords": [],
  "license": "ISC",
  "browserslist": [
    "defaults",
    "ie 11"
  ]
}

We have Storybook in our project, but currently we are only testing the output of webpack --mode production in a static html file.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>IE Testing</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="./style.css">
    <script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
    <script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-bundle.js"></script>
    <script src="./index.js"></script>
    <script src="./components.js"></script>
</head>

<body>
    <!-- Template Start -->
    <pp-test-component></pp-test-component> // our own test component
    <!-- Template Ende -->
</body>
</html>

Acceptance criteria

IE11 must render the Web Components

web-padawan commented 4 years ago

Duplicate of #833, see also https://github.com/Polymer/lit-element/issues/883#issuecomment-577591359

As mentioned there, please make sure you are using babel.config.js.

fregiese commented 4 years ago

I am already using babel.config.js, the config is in the description of the issue.

web-padawan commented 4 years ago

You probably need to update your preset-env config to look like this:

[
  "@babel/preset-env",
  {
    modules: false,
    targets: {
      ie: 11
    }
  }
],
fregiese commented 4 years ago

I changed the babel.config.js to:

module.exports = {
    presets: [
        [
            '@babel/preset-env',
            {
                modules: false,
                targets: {
                    ie: 11,
                },
            },
        ],
    ],
    plugins: [
        [
            '@babel/plugin-proposal-decorators',
            {
                legacy: true,
            },
        ],
        '@babel/plugin-proposal-class-properties',
        [
            '@babel/plugin-transform-runtime',
            {
                regenerator: true,
            },
        ],
    ],
};

But IE11 sadly doesn't work, it gives me this error:

SCRIPT5007: Unable to set property 'wrap' of undefined or null reference
components.js (1,6277)
justinfagnani commented 4 years ago

Thanks @web-padawan for helping here.

Unfortunately, I'm not a Webpack expert. @fregiese could you make a minimal reproduction in a github repo or zip file that I can try out? Since I'm not great with Webpack, it would be helpful to eliminate all unnecessary configuration like the Scss loaders, etc.

arthurevans commented 4 years ago

When working on a rollup config, I ran into issues with the ordering of the polyfills, as described by @LarsDenBakker in https://github.com/Polymer/lit-element/issues/833#issuecomment-548846702.

My fix, like the one shown in that issue, involved removing babel-plugin-transform-runtime (which inlines the polyfills) and instead creating a separate bundle for the Babel polyfills, and importing them before the webcomponents polyfills, as shown in https://github.com/Polymer/lit-element/issues/833#issuecomment-559493194.

Hope that helps. If you can't get it working after looking at that, please make a repro that we can try to debug as @justinfagnani said.

sorvell commented 4 years ago

Closing based on the previous comments. Please re-open a new issue with more info if the problem persists.

fregiese commented 4 years ago

For people who have the same problems, we now have a working configuration:

One of the main problems was, that the regex didn't work windows machines, we now have this regex, that works for mac and windows:

{
    test: /\.js$/,
    exclude: /[\\/]node_modules[\\/](?!(lit-element|lit-html)[\\/]).*/,
    use: 'babel-loader',
},

Before the regex was updated, lit-element and lit-html was not compiled with babel, like it is supposed to as stated here: https://lit-element.polymer-project.org/guide/start under "Supporting older browsers"

babel.config.js

module.exports = {
    presets: [
        '@babel/preset-env',
    ],
    plugins: [
        [
            '@babel/plugin-proposal-decorators',
            {
                legacy: true,
            },
        ],
        '@babel/plugin-proposal-class-properties',
        [
            '@babel/plugin-transform-runtime',
            {
                regenerator: true,
            },
        ],
    ],
};

So the steps for us to get it working in IE11 was:

  1. Import @webcomponents/webcomponentsjs Polyfill
  2. Use regex to include lit-element and lit-html when compiling with babel
  3. Use babel.config.js as seen above
web-padawan commented 4 years ago

@fregiese thanks for putting it together. My comments at https://github.com/Polymer/lit-element/issues/883#issuecomment-577591359 and https://github.com/Polymer/lit-element/issues/883#issuecomment-577651183 describe the same, but your comment looks cleaner and should be helpful for beginners.

fregiese commented 4 years ago

@web-padawan Yes, I wanted to make a closing statement, because your comments helped me to get a working configuration. So I wanted to share it with other users who have trouble, are finding this issue and don't have a deep understanding of how it all works together. Thanks for the help!

infoanishgarg commented 1 year ago

You are a gem @fregiese , your suggestion worked straightforwardly . I was struggling a lot with this. May Thanks.