Вашему веб-сайту может не потребоваться сборка внешнего интерфейса

внешний интерфейс
Вашему веб-сайту может не потребоваться сборка внешнего интерфейса

В этой статье используется лицензионное соглашение «Signature 4.0 International (CC BY 4.0)», добро пожаловать на перепечатку или изменение для использования, но вам необходимо указать источник.Атрибуция 4.0 Международная (CC BY 4.0)

Автор этой статьи: Су Ян

Создано: 27 мая 2019 г. Статистические слова: 8760 слов Время чтения: 18 минут на чтение Ссылка на эту статью:Поиск teay.com/2019/05/27/…


Вашему веб-сайту может не потребоваться сборка внешнего интерфейса

несколько лет назадWebpackзамененыGulp,GruntПосле этого мы ясно видим, что инженерная сложность фронтенд-проектов становится все выше и выше, а скорость итерации фронтенд-технологий становится все быстрее и быстрее.

Будь то большой завод или учебный класс, все это направлено наWebpack, Вавилон, ESLintТри гиганта в области передовых инженерных инструментов поделились бесчисленным количеством примеров.

Но из этого следует, что фронтенд-проекты уже почти не такие "простые и приятные", как раньше. Если вы хотите написать проект на популярном фреймворке, то, как правило, сначала нужно выполнить скаффолдинг. Если программа, которую вы пишете, не имеет "опыта фасадного строительства", Стесняетесь поздороваться с коллегами.

В этой статье будут использованы два простых примера, чтобы проиллюстрировать, что даже без строительных лесов и с помощью некоторых «старичков» вы можете разработать высокопроизводительный веб-сайт.

Дополнительные примечания

эта статьяне полностью применимоСложные и плотные совместные проекты с командой из дюжины и более человек подходят только для небольших и средних проектов, таких как простой фон, настройка процесса и даже демонстрация.

После долгих размышлений приступимНазад к счастливой фронтенд-разработке.

Начните с простого «одностраничного» приложения

ли с помощьюReact,VueИли используйте более винтажныйjQuery, чтобы сделать простую страницу, не более чем завершить написание трех частей: «структура страницы», «стиль страницы» и «функция страницы».

Мы используем более популярныеVueНапример:

<!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>简单的页面</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ant-design-vue@1.3.8/dist/antd.min.css">
    <!-- 你也可以选择保存在本地使用, 脚本资源也是一样 -->
    <!-- <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(255,255,255,.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}</style>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/ant-design-vue@1.3.8/dist/antd.min.js"></script>
</head>
<body>

    <div id="app">
        <a-layout>
           <a-layout-header id="header">
              <div class="logo">博客Logo摆放</div>
              <a-menu mode="horizontal" :defaultSelectedKeys="['1']" id="header-nav">
                 <a-menu-item key="1">首页</a-menu-item>
                 <a-menu-item key="2">
                    团队
                    <a-badge id="has-team-news" status="success"></a-badge>
                 </a-menu-item>
                 <a-menu-item key="3">标签</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="你不知道啥?问我鸭" />
           </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"></a-icon>
                                <span>推荐</span>
                             </span>
                             <a-menu-item key="1">牛逼的比赛</a-menu-item>
                             <a-menu-item key="2">犀利的观点</a-menu-item>
                             <a-menu-item key="3">给力的事件</a-menu-item>
                             <a-menu-item key="4">特别的曝光</a-menu-item>
                          </a-sub-menu>
                          <a-sub-menu key="sub1">
                             <span slot="title">
                                <a-icon type="html5"></a-icon>
                                <span>前端</span>
                             </span>
                             <a-menu-item key="1">最佳实践</a-menu-item>
                             <a-menu-item key="2">基础知识</a-menu-item>
                             <a-menu-item key="3">多彩样式</a-menu-item>
                             <a-menu-item key="4">有趣脚本</a-menu-item>
                          </a-sub-menu>
                          <a-sub-menu key="sub2">
                             <span slot="title">
                                <a-icon type="codepen"></a-icon>
                                <span>后端</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="7">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"></a-icon>
                                <span>运维</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"></a-icon>
                                <span>算法</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"></a-icon>
                                <span>分类</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"></a-icon>
                                <span>分类</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" autoplay>
                       <div>
                          <h3>凉风有幸 1</h3>
                       </div>
                       <div>
                          <h3>秋月无边 2</h3>
                       </div>
                       <div>
                          <h3>啦啦啦啦 3</h3>
                       </div>
                       <div>
                          <h3>置顶精选 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>
                                编辑精选
                             </a-menu-item>
                             <a-menu-item key="2">
                                <a-icon type="user"></a-icon>
                                最新发布
                             </a-menu-item>
                          </a-menu>
                          <a-button style="margin-left: 8px">
                             编辑精选
                             <a-icon type="down" />
                          </a-button>
                       </a-dropdown>
                       <div id="top-switch-2">
                          <a href="#">热门</a>
                          <a-divider type="vertical"></a-divider>
                          <a href="#" class="grey">最新</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: '暂无数据'}">
                          <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%">
                                <h2>这是一篇博客的标题,可能很长很长很长很长</h2>
                                <div class="post-meta">
                                   <a-icon type="user"></a-icon>
                                   @nickname
                                </div>
                                <div class="post-meta">
                                   <a-icon type="clock-circle"></a-icon>
                                   10分钟前
                                </div>
                                </a-avatar>
                                <p class="desc">
                                   简单的内容描述。
                                </p>
                                <div style="float:left">
                                   <a-tag>前端</a-tag>
                                   <a-tag>工程工具</a-tag>
                                   <a-tag>方法论</a-tag>
                                </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"></a-icon>
                          这里是一个公告标题
                       </h3>
                       <p>这里有一个描述性词汇描述性词汇描述性词汇描述性词汇描述性词汇</p>
                       <a-button style="width:100%;background:#42b983;border-color: #42b983;color: #fff;">开始浏览
                       </a-button>
                    </a-card>
                    <a-card id="tag-list" style="margin: 10px;">
                       <h3>
                          <a-icon type="tag" style="margin-right: 8px"></a-icon>
                          热门标签
                       </h3>
                       <a-divider></a-divider>
                       <a-tag>前端</a-tag>
                       <a-tag>工程工具</a-tag>
                       <a-tag>方法论</a-tag>
                       <a-tag>工程工具</a-tag>
                       <a-tag>方法论</a-tag>
                       <a-tag>前端</a-tag>
                       <a-tag>方法论</a-tag>
                       <a-tag>工程工具</a-tag>
                       <a-tag>方法论</a-tag>
                       <a-tag>前端</a-tag>
                    </a-card>
                    <a-tabs defaultActiveKey="2" style="margin: 10px;" type="card" id="ranking">
                       <a-tab-pane tab="月度优秀作者" key="1">
                          <a-card id="car-list">
                             <div class="item-people">
                                <a-avatar style="margin-right:4px">1</a-avatar>
                                <a href="#">作者 - 简单描述</a>
                                <a-badge 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="#">作者 - 简单描述</a>
                                <a-badge 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="#">作者 - 简单描述</a>
                                <a-badge 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="#">作者 - 简单描述</a>
                                <a-badge style="zoom:0.8" count="7"
                                   :numberStyle="{backgroundColor: '#8bc34a'} " />
                             </div>
                             <div class="item-people">
                                <a-avatar style="margin-right:4px">5</a-avatar>
                                <a href="#">作者 - 简单描述</a>
                                <a-badge 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="#">作者 - 简单描述</a>
                                <a-badge style="zoom:0.8" count="2"
                                   :numberStyle="{backgroundColor: '#8bc34a'} " />
                             </div>
                          </a-card>
                       </a-tab-pane>
                       <a-tab-pane tab="月度优秀作者" key="2">
                          <a-card id="cars-list">
                             <div class="item-people">
                                <a-avatar style="margin-right:4px">1</a-avatar>
                                <a href="#">作者</a>
                                <a-badge 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="#">作者</a>
                                <a-badge 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="#">作者</a>
                                <a-badge 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="#">投稿</a>
                 <a-divider type="vertical"></a-divider>
                 <a href="#">关于</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>

Сохраните приведенные выше триста или около того строк кода какindex.html, используйте браузер, чтобы открыть его напрямую, вы безошибочно увидите следующий интерфейс.

一个简单的单页 Demo

После простого воспроизведения вы обязательно скажете, что эта выборка не имеет сложных взаимодействий, и это не официальноОдно из рекомендуемого использованияХорошо.

Да, но, надеюсь, вы сможете увидеть прошлые страницы, на которых написано что-то вроде приведенного выше.Его действительно не нужно «смешивать» с инструментами сборки., даже если вы заполните ту часть, с которой взаимодействует компонент.

В процессе разработки можно вернуться к классическому «обновлять при изменении», и что видите, то и получаете.

Далее поговорим о том, как разбить приведенную выше программу на модули, чтобы модули можно было повторно использовать между несколькими страницами, разумеется, без использования инструментов сборки.

Сплит функциональные модули

Абстрагирование и модульность функций единой ответственности можно назвать повседневной жизнью инженеров. Помимо улучшения удобства обслуживания, потенциального повышения производительности страниц и повышения гибкости разработки программного обеспечения, самым большим преимуществом этого является увеличение возможности повторного использования функциональных модулей.

Когда мы используем webpack каждый день, мы, должно быть, видели, что он разделен на кучу именованныхchunkсценарий для файла, или имя может называтьсяvendor,app,componentдокумент. Это программные модули, которые программа сборки вырезает для нас, даже те, которые представлены в примере выше.*.min.js.. тоже так.

Что, если мы не будем использовать инструменты сборки для разделения модулей? Какие здесь общие ямы?

  1. После разделения на несколько модулей потребуется дополнительный сбор сетевых ресурсов и обработка синтаксического анализа.
  2. После разделения на несколько модулей может потребоваться дополнительное управление зависимостями модулей.
  3. После разделения на несколько модулей будет задействовано управление синхронизацией данных и состояний.

Для решения первых двух задач можно использоватьRequire.jsтакие как загрузчик ресурсов, чтобы контролировать загрузку дополнительных файлов ресурсов после разделения и управлять зависимостями модулей.Если вы хотите узнать подробности об этом старом парне, вы можете просмотреть егоОфициальный сайт.

Для разделенных модулей, если вы хотите, чтобы написание было простым и ясным, здесь вы выбираете использование синтаксиса компонента Vue для сохранения модуля, поэтому вам нужно ввести дополнительныйпарсер модуля, принцип очень прост, поXHRПосле того, как метод получает ресурсы, контент извлекается в «стиль», «скрипт» и «шаблон» с использованием обычных правил, а затем выполняется в среде браузера в нужное время. Для упрощения яrequirejs-vueНа основе удаления можете посмотреть, если интересно.исходный код.

Что касается третьей проблемы, будь то использование синглтона для совместного использования источника данных, или использование режима публикации-подписки для передачи данных, или использование режима наблюдателя, способов ее решения еще много, так что я победил Не расширяйте его. Эта статья пока будет пропущена. Вы можете выбрать ту, которую вам удобно использовать.

Взяв в качестве примера приведенную выше одностраничную программу, мы сначала напишем фрейм страницы.

<!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>将模版分离</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/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();
            headerInst.$el.appendChild(header.$el);

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

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

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

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

По сравнению с примерно 300 строками кода в предыдущем разделе, которые смешаны с подробной логикой, этот код длиной менее 100 строк намного понятнее?

Я только что упомянул повторное использование модуля, что на самом деле очень просто.Например, если мы хотим реализовать «страницу списка», мы можем написать следующее:

<!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>复用模块的例子</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/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();
            headerInst.$el.appendChild(header.$el);

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

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

        });
    </script>
</body>
</html>

После разговора о структуре страницы давайте посмотрим, как написать разделяемые модули с помощью простогоheaderПример модуля:

<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">博客Logo摆放</div>
        <a-menu mode="horizontal" :defaultSelectedKeys="['1']" id="header-nav">
           <a-menu-item key="1">
              首页
           </a-menu-item>
           <a-menu-item key="2">
              团队
              <a-badge id="has-team-news" status="success"></a-badge>
           </a-menu-item>
           <a-menu-item key="3">
              标签
           </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="你不知道啥?问我鸭"></a-input-search>
     </div>
</template>

Как видите, это обычный шаблон компонента Vue.

Код для других модулей можно найти внашел здесь, метод расщепления аналогичен и здесь повторяться не будет.

Отличие от предыдущего подраздела в том, что мы использовалиXHRПоэтому, если вы используете браузер для прямого открытия HTML-страницы для предварительного просмотра эффекта, вы получите сообщение об ошибке, подобное следующему, и вы не сможете получить желаемый результат.

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. 

Решение здесь очень простое, достаточно закинуть страницу в программу, которая может предоставлять HTTP-сервисы, можно использовать такие решения, как Node (HTTP Server, Express, KOA), а можно использовать Apache, Nginx, Caddy... Выберите свой любимые инструменты в порядке.

В репозитории GitHub я предоставляюdocker-compose.ymlФайл оркестрации, если он установлен локальноDockerЕсли это так, просто клонируйте проект, а затем выполнитеdocker-compose up,Открытьlocalhost:10240/split.htmlВы можете увидеть результат предварительного просмотра.

不使用构建工具拆分页面模块的例子

Улучшение опыта

Если вы хотите получить опыт разработки, который обновляет страницу в режиме реального времени с помощью Webpack, вы можете рассмотреть возможность его глобальной установки.browsersyncЭтот инструмент, в дополнение к обновлению страницы в зависимости от того, был ли изменен файл, этот старый парень также может синхронизировать прокрутку, события кликов и другие интерактивные операции текущей страницы отладки на разных устройствах. Представление конкретных деталей этого инструмента выходит за рамки этой статьи.Заинтересованные партнеры могут посетить его официальный сайт:www.browsersync.io/ .

В этом примере мы разделили модуль на несколько.htmlХотя есть много запросов на файлы, они не могут использовать возможности комбо на стороне сервера, такие как традиционные сценарии и ресурсы стилей.

Однако, поскольку используется HTML, который не был создан и сжат, а некоторые конфигурации обновляются в режиме реального времени с помощью CMS, становится проще изменить функцию страницы. В конце концов, нет необходимости создавать релизную версию после запуска. (Вы можете узнать о модульном решении Taobao TMS)

看起来变多的请求

Кроме того, если вы действительно чувствительны к количеству запросов, вы можете оптимизировать загрузчик модулей, чтобы добиться чего-то вродеlsloaderНапример, локальное сильное кэширование + функции управления версиями ресурсов, что снижает количество запросов. Однако в 2019 году такое количество запросов совсем не проблема для мультиплексированного HTTP2, большая пропускная способность которого видна повсюду.

Даже если страница не открывается с использованием HTTPS (HTTP2), модульная разделенная страница работает лучше, чем неразделенная страница.

未拆分模块的页面

После того, как страница без модульного разделения будет обновлена, очевидно, появится дрожание белого экрана страницы.

进行了模块拆分的页面

На странице сплит-модулей отображение будет намного «плавнее».Конечно, если гонитесь за ультимейтом, можно добавить и каркасный экран.

Если приведенная выше анимация недостаточно понятна, вы можете увидеть тест производительности в двух случаях.

未拆分模块的页面

Первый кадр неразделенной страницы быстрый, но со сложностью бизнес-скрипта,Evaluate Scriptвремя будет увеличиваться и увеличиваться, что приведет кDOM Content LoadedБесконечная задержка вызовет ощущение отставания в пользовательском опыте.

进行了模块拆分的页面

После разделения модуля страницы,DOM Content LoadedСроки значительно увеличены, хотя общая сложность скрипта остается неизменной, сложность отдельного модуля становится меньше.DCLВремя увеличено, и время разбора скрипта модуля также увеличено.

наконец

Повторим еще раз: эта статья не означает, что наши проекты разработки не выполняют настройку скаффолдинга и вообще не используют отличные интерфейсные инструменты, такие как Webpack.

Смысл в том, что после того, как у нас появилась возможность построить среду разработки, в подходящих сценариях мы должны быть гибкими и гибкими, использовать более простые и быстрые решения для разработки, и высвободить время для настройки среды и установки модулей для более интересных вещей. .

Интерфейс в примере в этой статье см.https://love2.io/,掘金Дизайн, спасибо дизайнерам за их кропотливую работу.

—ЭОФ


Теперь у меня есть небольшая группа по метанию, в которую входят друзья, которые любят метать.

В отсутствие рекламы мы будем вместе болтать о софте, HomeLab и вопросах программирования, а также время от времени будем делиться технической информацией о салоне в группе.

Друзья, которые любят бросать, могут отсканировать код, чтобы добавить друзей. (Пожалуйста, укажите источник и цель, иначе не пройдет проверку)

Эти вещи о том, чтобы бросить группу в группу