1.0.3 • Published 4 years ago

dynamic-bundle-loader v1.0.3

Weekly downloads
2
License
ISC
Repository
github
Last release
4 years ago

dynamic-bundle-loader

dynamic import bundle and should be used for creating lazy-loaded component

install

npm install dynamic-bundle-loader

Usage

The original purpose of writing this loader is mainly to reduce the size of the first screen js, so that some components are only loaded when they are needed, such as clicking a button to pop up a modal box. The code of the modal box will not be loaded before clicking, but only be loaded after clicking. At the same time, you need to make the lazy-loaded component use as similar to the original use as possible. Therefore, i recommend using dynamic-bundle-loader to do this thing.

The following briefly shows how to use dynamic-bundle-loader in react and vue to lazily load component. What's more, the components that need to be lazy loaded are used as much as possible as the original components (but the related use of react hook is not provided for the time being, interested parties can refer to the following code to rewrite into the react hook version ). The code can be found in the "example" folder. Obviously, the function of the code may be incomplete.I just borrow and provide an simple idea.

1、React

Firstly, we define a Higher-Order Components called LazyLoader for loading components that need lazy loading.

import React, { Component } from 'react'

class LazyLoader extends Component {
    constructor(props) {
        super(props)
        this.state = {
            component: null,
            props: null
        };
        this._isMounted = false
    }

    componentWillMount() {
        this._load()
    }

    componentDidMount() {
        this._isMounted = true
    }

    componentWillReceiveProps(next) {
        if (next.component === this.props.component) {
            return null
        }
        this._load()
    }

    componentWillUnmount() {
        this._isMounted = false
    }

    async _load() {
        const module = await this.props.component()
        const component = module.default
        this.setState({
            component
        })
    }

    render() {
        const LazyComponent = this.state.component
        const props = Object.assign({}, this.props)
        delete props.component
        return LazyComponent ? (
            <LazyComponent {...props}/>
        ) : null
    }
}

export default LazyLoader

Now, let's see how to use LazyLoader for loading component lazily.

// Define a component that needs to be lazy loaded.
import React, { Component } from 'react'

class LazyComponent extends Component {
    render() {
        return (
            <div>
                this is a lazy Component!!!
            </div>
        );
    }
}

export default LazyComponent
import React, { Component } from 'react'
import ReactDOM from 'react-dom'

import LazyComponent from 'LazyLoader!./src/LazyComponent.js'
import LazyLoader from './src/lazyloader'


class App extends Component {
    constructor(props) {
        super(props)
        this.state = {
            isShowLazyLoader: false
        }

        this.handleClick = this.handleClick.bind(this)
    }

    handleClick() {
        const {isShowLazyLoader} = this.state
        this.setState({
            isShowLazyLoader: !isShowLazyLoader
        })
    }

    render() {
        const {isShowLazyLoader} = this.state
        return (
            <div>
                <button onClick={this.handleClick}>show lazyLoader</button>
                {
                    isShowLazyLoader && <LazyLoader component={LazyComponent}/>
                }
            </div>
        )
    }
}

ReactDOM.render(<App />, document.getElementById('root'))

It can be seen from the above code that if you need to lazy load the component (called LazyComponent in the code), you only need to pass the lazy-loaded component into LazyLoader as its props. Of course, the lazy-loaded components must be parsed by dynamic-bundle-loader. In the above code, we can see how to import lazy-loaded components in the code.

import LazyComponent from 'LazyLoader!./src/LazyComponent.js'

We added "LazyLoader!" in front of path, so we need to configure it in webpack.config.js.

module.exports = {
    resolveLoader: {
        alias: {
            LazyLoader: 'dynamic-bundle-loader'
        }
    },
}

Why do we need to import component like this and use such a webpack configuration? The reason is that not every component needs to be loaded lazily. In this way, we can only perform dynamic-bundle-loader parsing for components that need to be loaded lazily.

2、Vue

Similarly, we need to define a Higher-Order Components called LazyLoader for loading components that need lazy loading.

export default {
    name: 'lazy-loader',

    data() {
        return {
            lazyComponent: null,
            _isMounted: false
        }
    },

    props: {
        component: {
            type: Function,
            default: () => {}
        },

        props: {
            type: Object,
            default: () => ({})
        }
    },

    computed: {
        finalProps() {
            const props = Object.assign({}, this.props)
            return props
        }
    },

    methods: {
        async _load() {
            const module = await this.component()
            const component = module.default
            this.lazyComponent = component
        },
    },

    created() {
        this._load()
    },

    mounted() {
        this._isMounted = true
    },

    beforeDestroy() {
        this._isMounted = false
    },

    watch: {
        component(val, oldVal) {
            if (val === oldVal) return null
            this._load()
        }
    },

    render(createElement) {
        const LazyComponent = this.lazyComponent
        if(LazyComponent) {
            return createElement(
                LazyComponent,
                {
                    props: {...this.finalProps},
                    attrs: this.$attrs,
                    on: this.$listeners
                }
            )
        } else {
            return
        }
    }
}

And then define a component that needs to be lazy loaded.

<template>
    <div>
        this is a lazy Component!!!
        <div>{{count}}</div>
        <button @click="$emit('myclick')">emit click!!!</button>
    </div>
</template>

<script>
    export default {
        name: "lazyComponent",

        props: {
            count: {
                type: Number,
                default: 0
            }
        }
    }
</script>

<style scoped>

</style>

Now, let's see how to use LazyLoader for loading component lazily. Just see the code.

<template>
    <div>
        <button @click="handleClick">show lazyLoader</button>
        <LazyLoader v-if="isShowLazyLoader" :component="LazyComponent" :props="{count}" @myclick="emitMyClick"></LazyLoader>
    </div>
</template>

<script>
    import LazyLoader from './lazyLoader.js'
    import LazyComponent from 'LazyLoader!./lazyComponent.vue'
    export default {
        name: "index",

        data() {
            return {
                LazyComponent,
                isShowLazyLoader: false,
                count: 0
            }
        },

        components: {
            LazyLoader,
            LazyComponent: LazyComponent
        },

        methods: {
            handleClick() {
                this.count++
                this.isShowLazyLoader = !this.isShowLazyLoader
            },

            emitMyClick() {
                console.log('emit my click success!!!')
            }
        }
    }
</script>

Now, child components not only can receive props, but also can use "$emit" to notify the parent component.

1.0.3

4 years ago

1.0.2

4 years ago

1.0.1

4 years ago

1.0.0

4 years ago