aadsm / jsmediatags

Media Tags Reader (ID3, MP4, FLAC)
Other
758 stars 127 forks source link

Support dynamic import() from ES6 module #180

Open BeeDice opened 1 year ago

BeeDice commented 1 year ago

To reproduce:

<head>
    <script type="module">
        import('https://cdnjs.cloudflare.com/ajax/libs/jsmediatags/3.9.5/jsmediatags.min.js');
    </script>
</head>

Error:

Uncaught TypeError: Cannot use 'in' operator to search for 'Object' in undefined
    at $jscomp.polyfill (jsmediatags.min.js:2:113)
    at jsmediatags.min.js:2:257

Reason is that this is undefined in ES6 modules:

$jscomp.global = $jscomp.getGlobal(this);  // === undefined

I understand we use this here to support Node. Can getGlobal() return window if it is passed undefined?

Cattn commented 4 months ago

This.

SunboX commented 3 weeks ago

I did it like this:

I created a new "project" with a package.json file:

{
    "name": "YOU_NAME_IT",
    "version": "3.9.7",
    "scripts": {
        "build": "npx webpack"
    },
    "devDependencies": {
        "jsmediatags": "^3.9.7",
        "@babel/core": "^7.26.0",
        "@babel/preset-env": "^7.26.0",
        "babel-loader": "^9.2.1",
        "webpack": "^5.95.0",
        "webpack-cli": "^5.1.4"
    }
}

Than I created a webpack.config.js file like this:

module.exports = {
    mode: 'production',
    entry: './src/index.js',
    output: {
        filename: 'jsmediatags.mjs',
        path: __dirname + '/dist',
        libraryTarget: 'module'
    },
    experiments: {
        outputModule: true
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                loader: 'babel-loader',
                exclude: /node_modules/
            }
        ]
    }
}

and a .babelrc file like this:

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

I also create a folder src containing one file index.js like this:

const jsmediatags = require('../node_modules/jsmediatags/dist/jsmediatags.min.js')
export default jsmediatags

export class MediaTagReader {
    static read(file, options) {
        return new Promise((resolve, reject) => {
            new jsmediatags.Reader(file).read({
                onSuccess: resolve,
                onError: reject
            })
        })
    }
}

after that, you simply run npm install and npm run build... and you're getting a new file jsmediatags.mjs inside the dist folder.

Usage

import { MediaTagReader } from '/PATH_TO_YOUR_PACKAGE_NAME/dist/jsmediatags.mjs'

try {
    const { tags } = await MediaTagReader.read('http://path_to_your.mp3')

    const picture = tags.picture
    if (picture) {
        const { data, format } = picture
        const byteArray = new Uint8Array(data)
        const blob = new Blob([byteArray], { type: format })
        const url = URL.createObjectURL(blob)

        console.log('Album cover found in this MP3 file:', url)

        URL.revokeObjectURL(url)
    } else {
        console.log('No album cover found in this MP3 file.')
    }
} catch (error) {
    console.error('Error reading tags:', error.type, error.info)
}

Hope that helps someone. :)