This article is licensed under a “CC BY 4.0” license. You are welcome to reprint or modify this article, but the source must be noted. 4.0 International (CC BY 4.0)

By Su Yang

Creation time: May 27, 2019, statistical word count: 8760 words reading time: 18 minutes to read this article links: soulteary.com/2019/05/27/…


Your site may not need a front-end build

Since Gulp and Grunt were replaced by Webpack a few years ago, it has become clear that front-end projects are becoming more engineering complex and that front-end technologies are iterating faster.

Webpack, Babel, and ESLint front-end engineering tools have all contributed countless examples and examples.

But as a result, front-end projects are not as “easy and happy” as they used to be. Writing a project in a popular framework usually requires a complete scaffolding, and if you write a program that doesn’t “go through the front-end build,” you’ll be embarrassed to greet your peers.

This article will show you two simple examples of how you can develop a high-performance web site without scaffolding and with a few old guys.

Additional instructions

This article is not entirely suitable for complex, high-density collaborative projects with teams of dozens or more, but only for small to medium sized projects, such as simple back ends, process configurations, and even demos.

With all this chatter, let’s officially get back to the fun of front-end development.

Start with a simple “one-page” application

Whether using React, Vue or jQuery with more sense of age, to make a simple page, it is no more than completing the writing of “page structure”, “page style” and “page function” respectively.

Let’s use the popular Vue as an example:

<! DOCTYPE html> <html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge"</title> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/antd.min.css"> <! -- You can also choose to save it for local use, as well as script resources --> <! -- <link rel="stylesheet" href="Assets/common/antd - v1.3.8. Min. CSS"> -->
    <style>body{color:#2c3e50}#header{height:50px; background:#fff; border-bottom:1px solid #eceef1}#header-nav{float:left; height:50px}#header-search{float:right; width:180px; margin:4px}#header-button{float:right; height:50px; overflow:hidden; line-height:50px}#has-team-news{top:-7px; left:-3px}.logo{width:120px; height:100%; line-height:50px; font-weight:bold; Background: rgba (255255255, 2); float:left}#left-menu{margin-top:10px}#left-menu-wrap{padding-left:10px; margin-left:10px}#top-switch{margin-top:10px; overflow:hidden}#top-switch-2{float:right; overflow:hidden; width:100px; height:20px; line-height:20px; margin-top:10px}#top-switch-2 a{font-size:12px}#top-switch-2 a.grey{color:gray}#top-divider{margin:10px}#post-container{margin:10px}.slick-slide{text-align:center; height:160px; line-height:160px; background:#364d79; overflow:hidden}.slick-slide h3{color:#fff}#carousel{margin:10px}.demo-loadmore-list{min-height:350px}.post-meta{display:inline-block; font-size:13px; line-height:13px; height:13px; overflow:hidden; font-style:italic; margin-right:4px}.desc{margin:14px 0; font-size:16px}#tag-list .ant-tag{margin-bottom:8px}.item-people{margin:10px 0}#ranking .ant-tabs-top-bar{margin-bottom:0}#car-list,#cars-list{border-top:none}
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/antd.min.js"></script>
</head>
<body>

    <div id="app">
        <a-layout>
           <a-layout-header id="header">
              <div class="logo"Word-wrap: break-word! Important; "> < span style =" box-sizing: border-box; color: RGB (74, 74, 74)"horizontal" :defaultSelectedKeys="[' 1 ']" id="header-nav">
                 <a-menu-item key="1"> Home </a-menu-item> <a-menu-item key="2"< p style = "text-align: center"has-team-news" status="success"></a-badge>
                 </a-menu-item>
                 <a-menu-item key="3"> Tag </a-menu-item> </a-menu> <a-button-group id="header-button">
                 <a-button icon="file-text"></a-button>
                 <a-button icon="star"></a-button>
                 <a-button icon="user"></a-button>
              </a-button-group>
              <a-input-search id="header-search" placeholder="What don't you know? Ask me duck" />
           </a-layout-header>
           <a-layout-content>
              <a-row type="flex">
                 <a-col :span="4">
                    <div id="left-menu-wrap">
                       <a-menu id="left-menu" mode="inline" :openKeys="openKeys" @openChange="onMenuOpenChange">
                          <a-sub-menu key="sub0">
                             <span slot="title">
                                <a-icon type="home"- icon > < / a > < span > recommended < / span > < / span > < a - menu - item key ="1"Word-wrap: break-word! Important; "> < span style =" box-sizing: border-box; color: RGB (50, 50, 50)"2"Word-wrap: break-word! Important; "> < span style =" max-width: 100%; clear: both"3"</a-menu-item> <a-menu-item key="4"> Special exposure </a-menu-item> </a-sub-menu> < A-sub-menu key="sub1">
                             <span slot="title">
                                <a-icon type="html5"- icon > < / a > < span > front end < / span > < / span > < a - menu - item key ="1"> Best practices </a-menu-item> <a-menu-item key="2"> Basic knowledge </a-menu-item> <a-menu-item key="3"> Color style </a-menu-item> <a-menu-item key="4"Interesting script > < / a - menu item - > < / a - sub menu > - < a - sub - menu key ="sub2">
                             <span slot="title">
                                <a-icon type="codepen"- icon > < / a > < span > back-end < / span > < / span > < a - menu - item key ="5">Option 5</a-menu-item>
                             <a-menu-item key="6">Option 6</a-menu-item>
                             <a-sub-menu key="sub3" title="Submenu">
                                <a-menu-item key="Seven">Option 7</a-menu-item>
                                <a-menu-item key="8">Option 8</a-menu-item>
                             </a-sub-menu>
                          </a-sub-menu>
                          <a-sub-menu key="sub3">
                             <span slot="title">
                                <a-icon type="appstore"- icon > < / a > < span > operations < / span > < / span > < a - menu - item key ="9">Option 9</a-menu-item>
                             <a-menu-item key="10">Option 10</a-menu-item>
                             <a-menu-item key="11">Option 11</a-menu-item>
                             <a-menu-item key="12">Option 12</a-menu-item>
                          </a-sub-menu>
                          <a-sub-menu key="sub4">
                             <span slot="title">
                                <a-icon type="html5"- icon > < / a > < span > method < / span > < / span > < a - menu - item key ="9">Option 9</a-menu-item>
                             <a-menu-item key="10">Option 10</a-menu-item>
                             <a-menu-item key="11">Option 11</a-menu-item>
                             <a-menu-item key="12">Option 12</a-menu-item>
                          </a-sub-menu>
                          <a-sub-menu key="sub5">
                             <span slot="title">
                                <a-icon type="html5"- icon > < / a > < span > categories < / span > < / span > < a - menu - item key ="9">Option 9</a-menu-item>
                             <a-menu-item key="10">Option 10</a-menu-item>
                             <a-menu-item key="11">Option 11</a-menu-item>
                             <a-menu-item key="12">Option 12</a-menu-item>
                          </a-sub-menu>
                          <a-sub-menu key="sub6">
                             <span slot="title">
                                <a-icon type="html5"- icon > < / a > < span > categories < / span > < / span > < a - menu - item key ="9">Option 9</a-menu-item>
                             <a-menu-item key="10">Option 10</a-menu-item>
                             <a-menu-item key="11">Option 11</a-menu-item>
                             <a-menu-item key="12">Option 12</a-menu-item>
                          </a-sub-menu>
                       </a-menu>
                    </div>
                 </a-col>
                 <a-col :span="14">
                    <a-carousel id="carousel"The autoplay > < div > < h3 > cool breezes to 1 < / h3 > < / div > < div > < h3 > moon with 2 < / h3 > < / div > < div > < h3 > la la la la 3 < / h3 > < / div > < div > < h3 > set-top selected 4 < / h3 > </div> </a-carousel> <div id="top-switch">
                       <a-dropdown>
                          <a-menu slot="overlay" @click="handleTopMenuClick">
                             <a-menu-item key="1">
                                <a-icon type="user"></a-icon> Edit selection </a-menu-item> <a-menu-item key="2">
                                <a-icon type="user"></a-icon> </a-menu> </a-menu> <a-button style="margin-left: 8px"> select <a-icontype="down" />
                          </a-button>
                       </a-dropdown>
                       <div id="top-switch-2">
                          <a href="#"Divider = divider </ dividertype="vertical"></a-divider>
                          <a href="#" class="grey"> new < / a > < / div > < a - divider id ="top-divider"></a-divider>
                    </div>
                    <div id="post-container">
                       <a-list class="demo-loadmore-list" :pagination="pagination" :loading="loading"
                          itemLayout="horizontal" :dataSource="postDataSource" :locale="{emptyText: 'no data '}">
                          <div v-if="showLoadingMore" slot="loadMore"
                             :style="{ textAlign: 'center', marginTop: '12px', height: '32px', lineHeight: '32px' }">
                             <a-spin v-if="loadingMore" />
                             <a-button v-else @click="onLoadMore">loading more</a-button>
                          </div>
                          <a-list-item v-for="(item, index) in postDataSource">
                             <a-card style="width:100%"Word-wrap: break-word! Important; "> < span style =" max-width: 100%"post-meta">
                                   <a-icon type="user"></a-icon>
                                   @nickname
                                </div>
                                <div class="post-meta">
                                   <a-icon type="clock-circle"">< div style =" box-sizing: border-box; color: RGB (50, 50, 50)"desc"> Simple content description. </p> <div style="float:left"> < a - tag > front - the tag < / a > < a - tag > engineering tools - the tag < / a > < a - tag > methodology - the tag < / a > < / div > < div class ="post-meta" style="float:right">
                                   <span>
                                      <a-icon type="like" style="margin-right: 8px"></a-icon>
                                   </span>
                                   <span>
                                      <a-icon type="star" style="margin-right: 8px"></a-icon>
                                   </span>
                                   <span>
                                      <a-icon type="message" style="margin-right: 8px"></a-icon>
                                   </span>
                                </div>
                             </a-card>
                          </a-list-item>
                       </a-list>
                       <a-pagination :defaultCurrent="6" :total="500" />
                    </div>
                 </a-col>
                 <a-col :span="6">
                    <a-card style="margin: 10px; border-color: #42b983;">
                       <h3 style="color:#42b983">
                          <a-icon type="notification" style="margin-right: 8px">< span style= "box-sizing: border-box! Important; word-break: break-word! Important;"width:100%; background:#42b983; border-color: #42b983; color: #fff;"> Start browsing </a-button> </a-card> <a-card id="tag-list" style="margin: 10px;">
                       <h3>
                          <a-icon type="tag" style="margin-right: 8px"Popular tags - icon > < / a > < / h3 > < a divider - > < / a - divider > < a - tag > front - the tag < / a > < a - tag > engineering tools - the tag < / a > < a - tag > methodology - the tag < / a > < a - tag > engineering tools - the tag < / a > < a - tag > methodology - the tag < / a > < a - tag > front - the tag < / a > < a - tag > methodology - the tag < / a > < a - tag > engineering tools - the tag < / a > < a - tag > methodology - the tag < / a > < A-tag > front end </ A-tag > </a-card> < A-tabs defaultActiveKey="2" style="margin: 10px;" type="card" id="ranking">
                       <a-tab-pane tab="Author of the Month" key="1">
                          <a-card id="car-list">
                             <div class="item-people">
                                <a-avatar style="margin-right:4px">1</a-avatar>
                                <a href="#"Word-wrap: break-word! Important; "> < span style=Zoom: "0.8" count="12"
                                   :numberStyle="{backgroundColor: '#8bc34a'} " />
                             </div>
                             <div class="item-people">
                                <a-avatar style="margin-right:4px">2</a-avatar>
                                <a href="#"Word-wrap: break-word! Important; "> < span style=Zoom: "0.8" count="10"
                                   :numberStyle="{backgroundColor: '#8bc34a'} " />
                             </div>
                             <div class="item-people">
                                <a-avatar style="margin-right:4px">1</a-avatar>
                                <a href="#"Word-wrap: break-word! Important; "> < span style=Zoom: "0.8" count="9"
                                   :numberStyle="{backgroundColor: '#8bc34a'} " />
                             </div>
                             <div class="item-people">
                                <a-avatar style="margin-right:4px">4</a-avatar>
                                <a href="#"Word-wrap: break-word! Important; "> < span style=Zoom: "0.8" count="Seven"
                                   :numberStyle="{backgroundColor: '#8bc34a'} " />
                             </div>
                             <div class="item-people">
                                <a-avatar style="margin-right:4px">5</a-avatar>
                                <a href="#"Word-wrap: break-word! Important; "> < span style=Zoom: "0.8" count="6"
                                   :numberStyle="{backgroundColor: '#8bc34a'} " />
                             </div>
                             <div class="item-people">
                                <a-avatar style="margin-right:4px">6</a-avatar>
                                <a href="#"Word-wrap: break-word! Important; "> < span style=Zoom: "0.8" count="2"
                                   :numberStyle="{backgroundColor: '#8bc34a'} " />
                             </div>
                          </a-card>
                       </a-tab-pane>
                       <a-tab-pane tab="Author of the Month" key="2">
                          <a-card id="cars-list">
                             <div class="item-people">
                                <a-avatar style="margin-right:4px">1</a-avatar>
                                <a href="#"Word-wrap: break-word! Important; "> < span style=Zoom: "0.8" count="109"
                                   :numberStyle="{backgroundColor: '#8bc34a'} " />
                             </div>
                             <div class="item-people">
                                <a-avatar style="margin-right:4px">1</a-avatar>
                                <a href="#"Word-wrap: break-word! Important; "> < span style=Zoom: "0.8" count="109"
                                   :numberStyle="{backgroundColor: '#8bc34a'} " />
                             </div>
                             <div class="item-people">
                                <a-avatar style="margin-right:4px">1</a-avatar>
                                <a href="#"Word-wrap: break-word! Important; "> < span style=Zoom: "0.8" count="109"
                                   :numberStyle="{backgroundColor: '#8bc34a'} " />
                             </div>
                          </a-card>
                       </a-tab-pane>
                    </a-tabs>
                 </a-col>
              </a-row>
           </a-layout-content>
           <a-layout-footer>
              <div>
                 <a-divider>-EOF-</a-divider>
                 <a-divider type="vertical"></a-divider>
                 <a href="#"Divider </ divider > </ dividertype="vertical"></a-divider>
                 <a href="#"> about < / a > < / div > < / a - layout - footer > < / a - layout > < / div > < script > Vue. Use (antd); const posts = [[],[],[],[],[],[],] var app = new Vue({ el:'#app'.data() {
        return {
            rootSubmenuKeys: ['sub0'.'sub1'.'sub2'.'sub3'.'sub4'.'sub5'.'sub6'],
            openKeys: ['sub0'],

            loading: true,
            loadingMore: false,
            showLoadingMore: true,
            postDataSource: posts,

            pagination: {
                onChange: (page) => {
                    console.log('Change Page', page);
                },
                pageSize: 3,
            },

        }
    },
    mounted() {
        this.getData((res) => {
            this.loading = false
            this.postDataSource = res
        })
    },
    methods: {
        onMenuOpenChange(openKeys) {
            const latestOpenKey = openKeys.find(key => this.openKeys.indexOf(key) === -1)
            if (this.rootSubmenuKeys.indexOf(latestOpenKey) === -1) {
                this.openKeys = openKeys
            } else {
                this.openKeys = latestOpenKey ? [latestOpenKey] : []
            }
        },

        handleButtonClick(e) {
            console.log('Button Clicked', e);
        },
        handleTopMenuClick(e) {
            console.log('Top Menu Clicked', e);
        },

        getData(callback) {
            setTimeout(() => {
                callback(posts)
            }, 300)
        },
        onLoadMore() {
            this.loadingMore = true
            this.getData((res) => {
                this.postDataSource = this.postDataSource.concat(res)
                this.loadingMore = false
                this.$nextTick(() => {
                    window.dispatchEvent(new Event('resize'))
                })
            })
        },

    },
})
</script>

</body>
</html>
Copy the code

Save the 300 or so lines of code above as index. HTML, open it directly in your browser, and you should see the following interface.

After playing around with it, you can tell that the sample page doesn’t have any complicated interactions, and that it’s one of the official recommended uses.

Yes, but hopefully you can see that a page like this does not really have to be “plugged” into the build tool, even if you fill out the component interactions.

In development, you can go back to the classic “change as you go, refresh as you go.” What you see is what you get.

Next, let’s talk about how to break the above application into modules so that modules can be reused across multiple pages, without using a build tool.

Splitting function modules

Modularizing the functions of a single responsibility is, as it were, everyday for engineers. In addition to improved maintainability, potentially improved page performance, and more flexible software builds, the biggest benefit is increased reusability of functional modules.

In our daily use of WebPack, we must have seen scripts split into chunks called chunk files, or files with names like Vendor, App, component. These are the software modules that the builder helps us cut, even the *.min.js introduced in the example above. And so it is.

What if we don’t use build tools for module splitting? What are the common pits?

  1. When split into modules, additional network resource acquisition and resolution processing are involved.
  2. After splitting into modules, additional module dependency management may be involved.
  3. After splitting into multiple modules, data and state synchronization management will be involved.

To solve the first two problems, you can use a resource loader such as require. js to control the loading of additional resource files and dependency management of modules. For details of this old thing, you can visit its official website.

For the split module, in order to keep the writing simple and straightforward, Vue’s Component syntax is chosen to save the module. Therefore, an additional module parser is needed. The principle is simple: after resources are obtained through XHR method, the contents are extracted into “style”, “script” and “template” using regular expressions. It is then executed in the browser environment at the appropriate time. To make things easier, I’ve trimmed down requirejs-Vue, and you can check out the source code if you’re interested.

As for the third problem, whether it’s using singletons to share data sources, or using publish/subscribe to deliver data, or using the Observer pattern, there are many ways to solve this problem, but I won’t extend it for the time being, so you can use whichever one you feel comfortable with.

In the example of the single-page program above, let’s write the page frame first.

<! DOCTYPE html> <html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge"> </title> <link rel="stylesheet" href="Assets/common/antd - v1.3.8. Min. CSS">

    <script src="Assets/common/vue - v2.6.10. Min. Js." "></script>
    <script src="Assets/common/moment - v2.24.0. Min. Js." "></script>
    <script src="Assets/common/antd - v1.3.8. Min. Js." "></script>

    <script src="Assets/common/the require - v2.3.6. Min. Js." "></script>

    <script>
        Vue.use(antd);
        requirejs && requirejs.config({
            baseUrl: './assets',
            paths: { 'vue': 'common/require-vue' },
            config: { 'vue': { 'css': 'inject'.'templateVar': '__template__'}}}); </script> </head> <body> <div id="app">
        <a-layout>
            <a-layout-header id="header"></a-layout-header>

            <a-layout-content>
                <a-row type="flex">
                    <a-col id="navbar" :span="4"></a-col>
                    <a-col id="main" :span="14"></a-col>
                    <a-col id="sidebar" :span="6"></a-col>
                </a-row>
            </a-layout-content>

            <a-layout-footer id="footer"></a-layout-footer>
        </a-layout>
    </div>

    <script>
        requirejs([
            'vue! template/header.html'.'vue! template/footer.html'.'vue! template/navbar.html'.'vue! template/sidebar.html'.'vue! template/carousel.html'.'vue! template/feed.html',].function (header, footer, navbar, sidebar, carousel, feed) {

            var appInst = new Vue({ el: '#app' });

            var headerInst = new Vue({ el: '#header' });
            header.$mount(a); headerInst.$el.appendChild(header.$el);

            var footerInst = new Vue({ el: '#footer' });
            footer.$mount(a); footerInst.$el.appendChild(footer.$el);

            var navbarInst = new Vue({ el: '#navbar' });
            navbar.$mount(a); navbarInst.$el.appendChild(navbar.$el);

            var sidebarInst = new Vue({ el: '#sidebar' });
            sidebar.$mount(a); sidebarInst.$el.appendChild(sidebar.$el);

            var mainInst = new Vue({ el: '#main' });
            carousel.$mount(a); mainInst.$el.appendChild(carousel.$el);
            feed.$mount(a); mainInst.$el.appendChild(feed.$el);
        });
    </script>
</body>
</html>
Copy the code

With less than 100 lines of code, isn’t it much more logical than the 300 lines of code in the previous section that mixed in with detailed logic?

If we want to implement a “list page”, we can write it like this:

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title> Example of reuse module </title> <link rel="stylesheet" href="Assets/common/antd - v1.3.8. Min. CSS">

    <script src="Assets/common/vue - v2.6.10. Min. Js." "></script>
    <script src="Assets/common/moment - v2.24.0. Min. Js." "></script>
    <script src="Assets/common/antd - v1.3.8. Min. Js." "></script>

    <script src="Assets/common/the require - v2.3.6. Min. Js." "></script>

    <script>
        Vue.use(antd);
        requirejs && requirejs.config({
            baseUrl: './assets',
            paths: { 'vue': 'common/require-vue' },
            config: { 'vue': { 'css': 'inject'.'templateVar': '__template__'}}}); </script> </head> <body> <div id="app">
        <a-layout>
            <a-layout-header id="header"></a-layout-header>
            <a-layout-content>
                <a-row type="flex">
                    <a-col :pull="5" :push="5" :span="14" id="main"></a-col>
                </a-row>
            </a-layout-content>
            <a-layout-footer id="footer"></a-layout-footer>
        </a-layout>
    </div>

    <script>
        requirejs([
            'vue! template/header.html'.'vue! template/footer.html'.'vue! template/list.html',].function (header, footer, submit) {
            var appInst = new Vue({ el: '#app' });

            var headerInst = new Vue({ el: '#header' });
            header.$mount(a); headerInst.$el.appendChild(header.$el);

            var footerInst = new Vue({ el: '#footer' });
            footer.$mount(a); footerInst.$el.appendChild(footer.$el);

            var mainInst = new Vue({ el: '#main' });
            submit.$mount(a); mainInst.$el.appendChild(submit.$el);

        });
    </script>
</body>
</html>
Copy the code

Now that we’re done talking about page frames, let’s take a look at how to write the split module, using a simple header module as an example:

<script>
define([], function() {
    return new Vue({
        template: __template__,
        data() {
            return{}},mounted() {},
        methods: {},
    })
});
</script>

<style>
#header{height:50px; background:#fff; border-bottom:1px solid #eceef1}#header-nav{float:left; height:50px}#header-search{float:right; width:180px; margin:4px}#header-button{float:right; height:50px; overflow:hidden; line-height:50px}#has-team-news{top:-7px; left:-3px}.logo{width:120px; height:100%; line-height:50px; font-weight:bold; background:rgba(255, 255, 255, .2); float:left}
</style>

<template>
    <div>
        <div class="logo"Word-wrap: break-word! Important; "> < span style =" box-sizing: border-box; color: RGB (74, 74, 74)"horizontal" :defaultSelectedKeys="[' 1 ']" id="header-nav">
           <a-menu-item key="1"> Home </a-menu-item> <a-menu-item key="2"< p style = "text-align: center"has-team-news" status="success"></a-badge>
           </a-menu-item>
           <a-menu-item key="3"> Tag </a-menu-item> </a-menu> <a-button-group id="header-button">
           <a-button icon="file-text"></a-button>
           <a-button icon="star"></a-button>
           <a-button icon="user"></a-button>
        </a-button-group>
        <a-input-search id="header-search" placeholder="What don't you know? Ask me duck"></a-input-search>
     </div>
</template>
Copy the code

As you can see, this is exactly the normal Vue component template.

The code for the other modules can be found here, broken up in much the same way, so I won’t go into detail here.

Unlike the previous section, because we are using XHR to get the resources, using the browser to directly open the HTML page to preview the results will not get the desired results like the following error.

Access to XMLHttpRequest at 'file:///Users/soulteary/You-Dont-Need-Webpack/src/assets/template/header.html' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https. 
Copy the code

The solution here is simply to throw the page into an application that can provide HTTP services. You can use Node (HTTP Server, Express, KOA) solutions, Apache, Nginx, Caddy… Just choose the tools that are handy to you.

In the GitHub repository, I provide a docker-compose. Yml file. If you have docker installed locally, just Clone the project and run docker-compose up. Open the localhost: 10240 / split. HTML preview can see the results.

Experience to enhance

If you want to get the experience of refreshing pages in real time with Webpack, consider installing BrowserSync globally. In addition to refreshing pages based on whether files have changed or not, browserSync can also synchronize scrolling, click events, and other interactions between the current debug page on different devices. Details of this tool are beyond the scope of this article. Interested partners can visit its official website: www.browsersync.io/.

In this case, we split the module into multiple.html files, although there are too many requests to enjoy the server Combo capabilities like traditional scripts and style resources.

But using HTML, without the obfuscation of build compression, and with the CMS updating some configurations in real time, making it easier to change the functionality of the page. After all, you don’t need to build a distribution once you’re online. (You can learn about taobao TMS modular solution)

In addition, if you are really sensitive to the number of requests, you can optimize the module loader to implement local strong caching + resource versioning functions such as lsloader to reduce the number of requests. However, in 2019, this number of requests is not a problem for multiplexing HTTP2 and the ubiquitous bandwidth.

Even if the page is not opened using HTTPS (HTTP2), the first screen experience of the modular split page is better than that of the unsplit page.

If a page is refreshed without modular splitting, white screen shake occurs.

The split-module page, on the other hand, is much “smoother”, although you can also add skeleton screens if you want to be extreme.

If the GIF above isn’t clear enough, you can see the performance test in both cases.

Although the first frame of the unsplit page is fast, with the complexity of the business Script, the Evaluate Script will take longer and longer, resulting in the infinite lag of DOM Content Loaded, which will bring a sense of lag in the user experience.

After the page module is split, the DOM Content Loaded time is greatly advanced. Although the overall script complexity is unchanged, the complexity of a single module is reduced. With the advance of DCL time, the completion time of module script parsing is also advanced.

The last

Again, this article is not to suggest that we develop projects without scaffolding and without good front-end tools like Webpack.

The point is that once you have the ability to set up a development environment, you need to be flexible in the right scenario and use a simpler, more agile approach to development, freeing up time to do more interesting things when configuring environments and installing modules.

The interface in this article examples, reference https://love2.io/, gold design, thanks to the hard work of the designers.

– EOF


I now have a small toss group, which gathered some like to toss about the small partners.

Without advertising, we would talk about software, HomeLab, programming issues, and also share some technical salon information in the group from time to time.

Like to toss friends welcome to scan code to add friends. (Please indicate source and purpose, otherwise it will not be approved)

All that stuff about being in a group