imsky / holder

:city_sunrise: Client-side image placeholders.
http://holderjs.com
MIT License
5.84k stars 592 forks source link

Using holder with webpack #198

Closed saneef closed 7 years ago

saneef commented 8 years ago

I'm trying to use 'Holder.js' with webpack. But, only getting dead ends.

When I try with require('holderjs');, I get holder.js:13 Uncaught TypeError: Cannot read property 'document' of undefined.

When I try with require('!imports?window=>this!holderjs'); using the import-loader, I get holder.js:13 Uncaught TypeError: Cannot read property 'document' of undefined.

Am I missing something here?

imsky commented 8 years ago

will look into this, Holder should work with bundlers

peterblazejewicz commented 7 years ago

@saneef Try:

yarn add holderjs
new webpack.ProvidePlugin({
            jQuery: 'jquery',
            $: 'jquery',
            jquery: 'jquery',
            Tether: 'tether',
            'window.Tether': 'tether',
            'window.Holder': 'holderjs'
        })
// 3rd party references
var jquery = require('jquery');
var tether = require('tether');
var bootstrap = require('bootstrap');
var holderjs = require('holderjs');
boogermann commented 7 years ago

@imsky any update on this issue? I have created a plugin for Vue.js that uses holder. Although I have it working while in the dev environment, once I pack a standalone version for production and import into another project I get the same error as @saneef "Uncaught TypeError: Cannot read property 'document' of undefined"

Here is the block where the error is thrown: the line that returns the error is: if (!global.document) return; if I change line 13 of your code reflects on this area of the packed version.

/**
 * Generic new DOM element function
 *
 * @param tag Tag to create
 * @param namespace Optional namespace value
 */
exports.newEl = function (tag, namespace) {
    if (!global.document) return;

    if (namespace == null) {
        return global.document.createElement(tag);
    } else {
        return global.document.createElementNS(namespace, tag);
    }
};

I've tried a variety of methods and babel plugins for the last 2 days with no luck, I have even included jquery, bootstrap and tether to the pack, but I still get the same error.

imsky commented 7 years ago

@boogermann i'm not sure exactly what's causing this. can you put together a reproducible case in a gist or git repo?

boogermann commented 7 years ago

@imsky while I was preparing something for you I think I have found the problem. I did a fine tuning on my webpack config file and was able to pack everything into a standalone version, but it will only work if I reference it in the html code. When I include the bundled version into another project, the error I've mention before happens. The problems seems to be onDomReady.js being executed before the Window Object is defined. I think it's the same problem mentioned on your readme about Meteor. When importing, Vue requires me to do a Vue.use(PLUGIN) to enable the plugin, but even without using it, and just doing the import the chunk of your code gets executed. So I think the best way here is have it serving both ways, people that are not using a bundler or transpiler can just use the compiled version, and rest just need to import from the source. I'll finish the documentation, create an example on jsfiddle and publish it to npm on weekend.

imsky commented 7 years ago

thanks @boogermann - this will be useful to include in docs for other vue/webpack users as well

LG0012 commented 7 years ago

Still not working, any solution? Using laravel webpack out of the box.

imsky commented 7 years ago

@LG0012 are you seeing the same bug as outlined in this issue? if so, could you provide a webpack config where you can replicate this bug? can be bare-bones, should just be able to replicate the issue.

boogermann commented 7 years ago

@imsky sorry for the long wait, I had the package done for a long time but was busy and completely forgot to publish my vue-holderjs package. It's also published on npm.

@LG0012 you can just use my plugin if you're using laravel with vue npm install vue-holderjs --save, otherwise you need to include this in your webpack config

plugins: [
    new webpack.ProvidePlugin({
        $: 'jquery',
        jQuery: 'jquery',
        'window.jQuery': 'jquery',
        Holder: 'holderjs',
        holder: 'holderjs',
        'window.Holder': 'holderjs'
    })
]
LG0012 commented 7 years ago

Thanks i will give a shot. :)

LG0012 commented 7 years ago

Well - http://prntscr.com/h6psau :)

This vue-holderjs is for vue2?

LG0012 commented 7 years ago

Its working now. I solved this by creating a new file with this content: http://prntscr.com/h6q0qv

And used just like that: http://prntscr.com/h6q0yh

boogermann commented 7 years ago

@LG0012 Yes, it's for vue2. I've setup a little demo when you import try vue-holderjs/src instead of just vue-holderjs and see if it works.

boogermann commented 7 years ago

@LG0012 There you go! 👍 I think I know where the problems is, the import gets the file from /dist. I'm doing some modifications here to have both options to use as a script source or import/require into a project.

LG0012 commented 7 years ago

I pretty sure you right :) Good work ;)

boogermann commented 7 years ago

@LG0012 Thanks, bumped to version 1.0.2 now it work as it suppose to. If you could give it a test I would appreciate it! JSFiddle was also updated to include more usage examples.

imsky commented 7 years ago

thanks for following up @boogermann

as i understand, the fix here is adding Holder/holder keys to the ProviderPlugin options. let me know if there's anything else.

will add a section on Webpack integration and vue-holderjs shortly.