GithubHelp home page GithubHelp logo

elemefe / obsolete-webpack-plugin Goto Github PK

View Code? Open in Web Editor NEW
183.0 9.0 14.0 318 KB

🌈 A Webpack plugin generates a browser-side standalone script that detects browser compatibility based on `Browserslist` and prompts website users to upgrade it.

License: MIT License

JavaScript 99.21% HTML 0.79%
webpack webpack-plugin obsolete outdated browserslist compatibility browser browser-update

obsolete-webpack-plugin's Introduction

Obsolete Webpack Plugin

npm npm npm npm node npm licenses

Introduction 🌟

A Webpack plugin generates a browser-side standalone script that detects browser compatibility based on Browserslist and prompts website users to upgrade it.

Motivation 💥

In modern front-end development, we use toolchain to convert next JavaScript version into a backwards compatible version of JavaScript that works in older browser environment. For next syntax features, such as Object Rest/Spread Properties, Exponentiation Operator, we can transform all of them through AST parser. For next built-in features, such as Promise, WeakMap, String.prototype.padstart, we can provide pollyfills that mimic native functionality. However, for some browser only features, such as Service Worker, WebAssembly, CSS Grid Layout, no polyfills support these or partially support. In the worst case, our users who use old browsers open a website but catch a sight of blank page. It may be a bad network condition, may be syntax parsing error, may be built-in losing. But they must not realize that the browser they using does not meet the requirements of our website target. Therefore, we need a mechanism to notify that they should upgrade their browser before accessing content. Thus, this plugin borns.

Getting Started ⚡

Prerequisite

  • Node >=8.3.0
  • Webpack 4.x

Installation

$ npm i -D obsolete-webpack-plugin

Basic Usage

Apply the plugin in your Webpack configuration, often used together with html-webpack-plugin. By the way, the putting order of plugins is irrelevant.

const HtmlWebpackPlugin = require('html-webpack-plugin');
const ObsoleteWebpackPlugin = require('obsolete-webpack-plugin');

module.exports = {
  // ...
  plugins: [
    // ...
    new HtmlWebpackPlugin(),
    new ObsoleteWebpackPlugin()
  ]
};

Best Practice

To improve first page load speed, you should always reduce render-blocking scripts as far as possible. For non-critical script, it's best to mark them with the async attribute. Thanks to script-ext-html-webpack-plugin, we are able to fulfill this goal easily.

const HtmlWebpackPlugin = require('html-webpack-plugin');
const ObsoleteWebpackPlugin = require('obsolete-webpack-plugin');
const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin');

module.exports = {
  // ...
  plugins: [
    new HtmlWebpackPlugin(),
    new ObsoleteWebpackPlugin({
      name: 'obsolete'
    }),
    new ScriptExtHtmlWebpackPlugin({
      async: 'obsolete'
    })
  ]
};

Configuration 📖

Options

Name Type Default Description
name string 'obsolete' The chunk name.
template string '<div>Your browser is not supported. <button id="obsoleteClose">&times;</button></div>' The prompt html template. It accepts any document fragment. E.g., '<style>...</style><div>...</div><script>...</script>'. Specially, the template will be removed when a node with attribute id="obsoleteClose" is clicked.
position string 'afterbegin' If set 'afterbegin', the template will be injected into the start of body.
If set 'beforeend', the template will be injected into the end of body.
browsers string[] Browsers to support, overriding global browserslist configuration.
promptOnNonTargetBrowser boolean false If the current browser useragent doesn't match one of the target browsers, it's considered as unsupported. Thus, the prompt will be shown. E.g., your browserslist configuration is ie > 8, by default, the prompt won't be shown on Chrome or Safari browser. E.g., your browserslist configuration is ie > 8, by default, the prompt won't be shown on Chrome or other browsers. Another e.g., your browserslist configuration is chrome > 80, by default, the prompt won't be shown on IE or other browsers.
promptOnUnknownBrowser boolean true If the current browser useragent is unknown, the prompt will be shown.

Demonstration 🎨

Browser Support 👓

The name matches Browserslist queries.

Desktop

IE Edge Chrome Safari Firefox Opera Electron

Mobile

ChromeAndroid Android
(5+, WebView)
iOS
(OS)

FAQ 🍵

Q: Does this plugin support Yandex, Maxthon, UC or QQ browser?

A: Yep. This plugin supports those browsers based on the mainstream browser kernel, such as Chromium based browser, Mozilla based browser. In other words, Chrome >= 30 will be also applied to Yandex browser, ChromeAndroid >= 30 will be also applied to Android UC browser.

Q: Does plugin work in IE 6?

A: Yep. This plugin supports browsers that implement the full ES3 spec. Although the source code is ES2015+, it will be compiled and shimmed to the target environment eventually.

obsolete-webpack-plugin's People

Contributors

chikara-chan avatar djaler avatar georgiyordanov avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

obsolete-webpack-plugin's Issues

Plugin doesn't generate js file

Environment

  • Plugin Version: 0.5.6
  • Webpack Version: 4.40.2
  • OS Version: Windows 10 / OS X Mojave
  • Node Version: Node 10
  • NPM Version: NPM 6
  • Browser Version: Firefox 69 / IE 11 / Edge 16

Current Behavior

Plugin doesn't generate a standalone JavaScript file.

Expected Behavior

Plugin should create a standalone JavaScript file.

Detailed Description

Here is my webpack.config.js:

/**
* Autor: Andre Sieverding
* Copyright © 2019
*/

const path = require('path')
const fs = require('fs')
const webpack = require('webpack')
const nodeExternals = require('webpack-node-externals')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const ObsoleteWebpackPlugin = require('obsolete-webpack-plugin')

// Get app configurations
var config = fs.readFileSync('config.json')
config = JSON.parse(config)

// Get node environment
const { NODE_ENV } = process.env
const isDev = NODE_ENV === 'development'
const env = isDev ? 'development' : 'production'

// Define webpack rules
const markoRule = {
    test: /\.marko?$/,
    loader: '@marko/webpack/loader'
}

const styleRule = {
    test: /\.(sass|scss|css)$/,
    use: [
        'style-loader',
        'css-loader',
        'sass-loader'
    ]
}

const vectorRule = {
    test: /\.svg/,
    loader: 'svg-url-loader'
}

const imageRule = {
    test: /\.(jpg|jpeg|gif|png|ico)$/,
    use: [
        {
            loader: 'file-loader',
            options: {
                name: 'images/[name]-[hash:8].[ext]'
            }
        }
    ]
}

const fontRule = {
    test: /\.(woff|woff2|ttf|eot)$/,
    use: [
        {
            loader: 'file-loader',
            options: {
                name: 'webfonts/[name]-[hash:8].[ext]'
            }
        }
    ]
}

// Webpack config for browser
const client = {
    name: 'Client',
    mode: env,
    entry: {
        app: isDev ? [
            'webpack-hot-middleware/client?reload=true',
            './app/client.js'
        ]: ['./app/client.js']
    },
    output: {
        filename: '[name].js',
        path: path.resolve(__dirname, 'dist'),
        publicPath: config.path + '/assets/'
    },
    devServer: isDev ? {
        contentBase: path.join(__dirname, 'dist'),
        historyApiFallback: true,
        overlay: true,
        hot: true,
        stats: 'minimal',
    } : undefined,
    devtool: isDev ? 'source-map' : undefined,
    resolve: {
        extensions: ['.js', '.json', '.marko']
    },
    module: {
        rules: [markoRule, styleRule, vectorRule, imageRule, fontRule]
    },
    plugins: [
        new webpack.ProvidePlugin({
            $: 'jquery',
            jQuery: 'jquery'
        }),
        new MiniCssExtractPlugin({
            filename: '[name].css'
        }),
        new ObsoleteWebpackPlugin({
            name: 'outdatedBrowser',
            promptOnNonTargetBrowser: true,
            template: '<div id="outdated"><h6>Dein Browser ist veraltet!</h6><p>Aktualisiere deinen Browser um diese Webanwendung zu verwenden. <a id="btnUpdateBrowser" href="http://fsg-vm-sccm/CMApplicationCatalog/#/SoftwareLibrary/AppListPageView.xaml">Browser jetzt updaten</a></p><p class="last"><a id="obsoleteClose" href="#" title="Schließen">&times;</a></p></div>'
        }),
        isDev && new webpack.HotModuleReplacementPlugin()
    ].filter(Boolean)
}

// Webpack config for server
const server = {
    name: 'Server',
    mode: env,
    target: 'node',
    externals: nodeExternals(),
    entry: {
        server: ['./app/server.js']
    },
    output: {
        filename: '[name].js',
        path: path.resolve(__dirname, 'dist'),
    },
    resolve: {
        extensions: ['.js', '.json', '.marko']
    },
    module: {
        rules: [markoRule, vectorRule, imageRule]
    }
}

module.exports = [
    server,
    client
]

False positive on Opera

Environment

  • Plugin Version: v0.5.6
  • Webpack Version: v4.43.0
  • OS Version: v10.15.6
  • Node Version: v10.16.0
  • NPM Version: v6.13.7
  • Browser Version: v60.0.3255.95

Browserlist:

"browserslist": [
    "Chrome > 60",
    "Safari >= 10.1",
    "iOS >= 10.3",
    "Firefox >= 60",
    "Edge >= 15",
    "Opera > 61"
  ]

Current Behavior

HTML Template is not served.

Expected Behavior

HTML Template appears since Opera v60.0.3255.95 is < v61

Detailed Description

Placing a console log here on line 944 in obsoleteweb/dist/obsolete.js:

return some(normalizedTargetBrowsersOfTheSameName, function (targetBrowser) {
	      return some(currentBrowsers, function (currentBrowser) {
					console.log(currentBrowser, targetBrowser)
	        return currentBrowser.name === targetBrowser.name && compareVersion(currentBrowser.primaryVersion, targetBrowser.primaryVersion) !== compareVersion.LT;
	      });
	    });

returns

Browser {name: "chrome", version: "73.0.3683.103", primaryVersion: "73"} 
Browser {name: "chrome", version: "61", primaryVersion: "61"}

The user agent is "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36 OPR/60.0.3255.95". I believe the UA parser/authenticator sees that Chrome 73 satisfies the browserslist requirements and returns true before it is able to see that it does not pass the Opera requirements.

Doesn't work with IE11 and ES6 scripts

Environment

  • Plugin Version: 0.5.6
  • Webpack Version: 4.35.3
  • OS Version: Windows 10 x64
  • Node Version: 10.11.0
  • NPM Version: 6.7.0
  • Browser Version: IE 11

Current Behavior

The browser stucks with error in main scripts (since ES6 incompatibility) and there is no any actions from obsolete.js

Expected Behavior

The browser should show the default obsolete-message

Detailed Description

How to reproduce

  1. Create any project with webpack 4 and obsolete-webpack-plugin
  2. Add to .browserslistrc with 'excluding of IE11' and any incompatible ES6 browsers (you can set the only last 5 Chrome version string)
  3. Add any ES6 script to index.js
  4. Compile and look into results in IE11 - browser finds the error in main.js and there are no actions from obsolete.js

It may be issue IE11, but how can it be resolved?

False positives on older Android Chrome versions

Environment

  • Plugin Version: 0.5.6
  • Webpack Version: 4.41.5
  • OS Version: OSX 10.15.2
  • Node Version: Node 10
  • NPM Version: NPM 6
  • Browser Version: Chrome 79.0.3945.117

We are trying to use this plugin to display an "unsupported browser" message on all versions of IE and versions of iOS earlier than 11 (as we know these browsers do not work with our apps.)

For all other browsers we do not want to show a message. With that in mind we are trying to use something like the following plugin settings:

{
  browsers: ["cover 100%, not iOS < 11, not IE <= 11"],
  promptOnUnknownBrowser: false,
  promptOnNonTargetBrowser: false
}

This does exactly what we need with one exception: versions of Chrome on Android earlier than 79 cause the message to appear which seems to be an issue with the query results:

npx browserslist "cover 100%, not iOS < 11, not IE <= 11"

and_chr 79
and_ff 68
<snip>

I realise this is not a direct issue with this plugin per-se but I am after any ideas we can use to stop the message appearing on Android Chrome short of forking this plugin and trying to add a hard-coded exception.

Update CoreJS to version 3

obsolete-web depends on @babel/runtime-corejs2 which is “no longer maintained and not recommended for usage due to the number of issues,” according to its install message.

Please update to version 3 of Core JS.

Feature: provide target browser to html template

Right now we can redefine html-template that showed for unsupported browsers via ```template`` option which is a string. But this is not convenient.

Better if it will be not only string but function also that provides list of supported browsers... So we can create html-template and show to a user all supported browsers.

For example right now I use the following:
webpack.config.js

const fs = require("fs");
const browserlist = fs.readFileSync("./.browserslistrc", "utf8");

const browserlistUri = browserlist
  .replace(/\r/g, "%2C")
  .replace(/\s/g, "+")
  .replace(/=/g, "%3D");

const ObsoleteTemplate = fs
  .readFileSync("./src/obsoleteBrowser.html", "utf8")
  .replace("{list}", browserlistUri);

...
    new ObsoleteWebpackPlugin({
        // it creates alert-script for not-supported browsers according to .browserlistrc
        name: "obsolete",
        promptOnNonTargetBrowser: true,
        template: ObsoleteTemplate
      }),
...

obsoleteBrowser.html

<div class="obsolete">
    <style>
     ...
    </style>
    <h4>Your browser is not supported (or older than required).</h4>
    <h5>
        It does not mean that site does not work but there are no guarantees that all will work fine.</br>
        All supported browsers you can find <a href="https://browserl.ist/?q={list}" target="_blank">here</a>
    </h5>
    <button id="obsoleteClose">&times;</button>
</div>

So you how you can see I implemented splitted html file and also js logic for reading .browserlistrc, *.html, parsing and preparing this to template. This is doesn't convenient a looks ugly. At the same time HtmlWebpackPlugin uses template as path-to-template option and I can use the global variables from the webpack inside such template.

My suggestion is:

  1. add templatePath option
  2. add some definition so you can get array of browsers into *.html
  3. update template option to string | function(listBrowsers) types

It will be fine if the configuring of this is more flexible.

Incompatibility with vue-cli modern mode

Environment

  • Plugin Version: 0.5.5
  • Webpack Version: 4.28.1
  • OS Version: Debian 9
  • Node Version: 10
  • NPM Version: 6
  • @vue/cli-service Version: 3.3.0

Current Behavior

Uncaught TypeError: Cannot set property 'Obsolete' of undefined when opened in modern browser with modules support

Expected Behavior

Work fine in both modern and legacy browsers

Detailed Description

Here are documentation about modern mode - https://cli.vuejs.org/guide/browser-compatibility.html#modern-mode

Support webpack 5

Environment

  • Plugin Version: 0.5.6
  • Webpack Version: 5.38.1
  • OS Version: Linux
  • Node Version: 16.2.0
  • NPM Version: 7.13.0
  • Browser Version: n/a

Current Behavior

Building with webpack 5 gives:

(node:1600) [DEP_WEBPACK_DEPRECATION_ARRAY_TO_SET_PUSH] DeprecationWarning: chunk.files was changed from Array to Set (using Array method 'push' is deprecated)ush (/srv/ledgersmb/node_modules/webpack/lib/util/deprecation.js:108:3)
    at ObsoleteWebpackPlugin.additionalAssets (/srv/ledgersmb/node_modules/obsolete-webpack-plugin/src/index.js:74:25)

Expected Behavior

No errors

Cannot work below ie10

Environment

IE 10, IE 9 and below

Current Behavior

Cannot work, and console the error ---- "Object does not support the "getElementById" property or method"

Expected Behavior

Can work

Detailed Description

I find this

 bindEvents(fragment) {
    const close = fragment.getElementById('obsoleteClose');

    if (!close) {
      return;
    }

In line 49, alert.js
But fragment.getElementById can't work under IE 10, https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment
Can it be replaced by fragment.querySelector, thank u~~~

Reduce size

Current Behavior

The current size of obsolete-web is 23 KB is too big for a small script to show a warning.

https://bundlephobia.com/[email protected]

Here is a good reminder that JS size is more important than picture size:

1_prvznizf9jq_qadf5lqhpa

Expected Behavior

Be at least 5 KB.

Detailed Description

@chikara-chan You can use Size Limit to find why obsolete-web is so big right now.

At least, you should remove core-js and other Babel runtime from this small script.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.