webpack插件编写_如何使用Webpack和渐进式Web技术编写简单的现代JavaScript应用程序...

仲和韵
2023-12-01

webpack插件编写

by Anurag Majumdar

通过阿努拉格·马朱达尔

如何使用Webpack和渐进式Web技术编写简单的现代JavaScript应用程序 (How to write simple modern JavaScript apps with Webpack and progressive web techniques)

Have you thought about making modern JavaScript applications with the simplest setup possible for your next project?

您是否考虑过用下一个项目的最简单设置制作现代JavaScript应用程序?

If so, you have come to the right place!

如果是这样,那么您来对地方了!

JavaScript frameworks exist to help us build applications in a generalized way with most of the common features. But most of the applications may not need all the powerful features of a framework. It may be overkill to just use a framework for specific requirements (especially small to medium scale projects).

存在JavaScript框架来帮助我们以大多数常用功能以通用方式构建应用程序。 但是大多数应用程序可能不需要框架的所有强大功能。 仅将框架用于特定需求(特别是中小型项目)可能会过大。

Today I am going to show an approach to how you can use modern features and build your own customized Web Applications. You can also build your own framework on top of the sample applications if you want to. That is purely optional. The power of Vanilla JavaScript enables us to follow our own coding style irrespective of the tools used.

今天,我将向您展示一种如何使用现代功能并构建自己的自定义Web应用程序的方法。 如果需要,您还可以在示例应用程序之上构建自己的框架。 那纯粹是可选的。 Vanilla JavaScript的强大功能使我们能够遵循自己的编码风格,而与所使用的工具无关。

我们需要的 (What We Need)

Before starting out, let us quickly skim through the features we need.

在开始之前,让我们快速浏览一下所需的功能。

建筑规划 (Architectural Planning)

To ensure fast loading and consistent experiences, we’ll use the following patterns:

为了确保快速加载和一致的体验,我们将使用以下模式:

  • Application Shell Architecture

    应用程序外壳架构
  • PRPL (Push, Render, Pre-cache, Lazy loading) pattern

    PRPL(P USH,R安德,P重新缓存,L AZY装载)图案

构建设置 (Build Setup)

We need a good custom build setup, so we will be using Webpack with the following requirements:

我们需要一个好的自定义构建设置,因此我们将使用具有以下要求的Webpack:

  • ES6 & Dynamic Imports support

    ES6和动态导入支持
  • SASS & CSS support

    SASS和CSS支持
  • Custom development & production setup

    定制开发和生产设置
  • Custom Service Worker Build

    定制服务工作者版本

裸露的最低JavaScript功能 (Bare Minimum JavaScript Features)

We will be touching on minimal JavaScript features to get us off the ground and produce the output we require. I will show you how we can use existing JavaScript ES6 features in our day to day vanilla applications. Here they are:

我们将介绍一些最小JavaScript功能,以使我们起步并产生所需的输出。 我将向您展示如何在日常的普通应用程序中使用现有JavaScript ES6功能。 他们来了:

  • ES6 Modules

    ES6模块
  • Dynamic Imports

    动态导入
  • Object Literal Syntax Or ES6 Class Syntax

    对象文字语法或ES6类语法
  • ES6 Arrow Functions

    ES6箭头功能
  • ES6 Template Literals

    ES6模板文字

At the end of this article there is a sample application demo along with its source code on GitHub. Let’s dig deeper, shall we? ?

在本文的最后,有一个示例应用程序演示及其在GitHub上的源代码。 让我们深入研究吧? ?

建筑规划 (Architectural Planning)

The advent of Progressive Web Applications has helped bring new architectures in order to make our first paint more effective. Combining App Shell and PRPL patterns can result in consistent responsiveness and app-like experiences.

渐进式Web应用程序的出现有助于引入新的体系结构,以使我们的第一幅画更有效。 结合使用App ShellPRPL模式可以产生一致的响应速度和类似App的体验。

什么是App Shell和PRPL? (What is App Shell & PRPL?)

App Shell is an architectural pattern for building Progressive Web Applications where you ship the minimal critical resources in order to load your site. This basically consists of all the necessary resources for the first paint. You may cache the critical resources as well using a service worker.

App Shell是用于构建渐进式Web应用程序的体系结构模式,您可以在其中运送最少的关键资源 为了加载您的网站。 这基本上包括第一个油漆的所有必要资源。 您也可以使用服务工作者来缓存关键资源。

PRPL refers to the following:

PRPL涉及以下内容:

  • Push critical resources (especially using HTTP/2) for the initial route.

    P USH临界资源(特别是使用HTTP / 2)对于初始路线。

  • Render the initial route.

    ř安德初始路径。

  • Pre-cache remaining routes or assets.

    P重新缓存剩余的路由或资产。

  • Lazy load portions of an application as and when required (especially when required by a user).

    大号 AZY应用程序在需要时(特别是在需要时通过用户)的负载部分。

这些架构在代码中是什么样的? (What Do These Architectures Look Like In Code?)

The App Shell and PRPL pattern are both used together to achieve the best practices.

App ShellPRPL模式一起使用以实现最佳实践。

The App shell looks somewhat like the following piece of code:

App Shell看起来类似于以下代码:

You can see that the application shell consists of the bare minimum markup as a skeleton.

您可以看到应用程序外壳程序由最低限度的标记作为框架组成。

Lines 9–82: Critical styles have been introduced into markup to ensure direct parsing of CSS instead of linking it to another file.

第9–82行 :标记中引入了关键样式,以确保直接解析CSS,而不是将其链接到另一个文件。

Lines 89–96: Main application shell markup; these areas will be later manipulated by JavaScript (especially, the contents inside the main tag of line 93).

第89–96行 :主应用程序shell标记; 这些区域稍后将由JavaScript处理(特别是第93行的main标签内的内容)。

Line 99: This is where the scripts come into play. The async attribute helps in not blocking the parser while the scripts get downloaded.

第99行 :这是脚本起作用的地方。 异步属性有助于在下载脚本时不阻止解析器。

The app shell also enforces Push & Render stages of the PRPL pattern. This happens when HTML is parsed by the browser to form pixels on the screen. It readily finds all the critical resources. Also, the critical scripts are responsible for showing the initial route by DOM manipulation (Render).

应用程序外壳程序还强制执行PR PL模式的PushRender阶段。 当浏览器解析HTML以在屏幕上形成像素时,就会发生这种情况。 它可以轻松找到所有关键资源。 同样, 关键脚本负责通过DOM操作( Render )显示初始路由

However, if we do not use a Service worker to cache the shell, it won’t be of any use for future reloads and performance benefits.

但是,如果我们不使用Service worker来缓存Shell,则对于将来的重新加载和性能提升将毫无用处。

The following code snippet shows a service worker which caches the shell and all the static assets required for the application.

以下代码片段显示了一个服务工作者,该服务工作者缓存了外壳程序和应用程序所需的所有静态资产。

Lines 4–17: The install event of service workers helps to cache all the static assets. Here, you can cache the app shell resources (CSS, JavaScript, images, etc.) for the first route (as per App shell). Also, you can cache the remainder of the assets of the application ensuring the whole app can run offline too. This caching of static assets apart from the main app shell ensures the Pre-cache stage of the PRPL pattern.

第4-17行 :Service Worker的install事件有助于缓存所有静态资产。 在这里,您可以为第一个路由(根据App Shell)缓存App Shell资源(CSS,JavaScript,图像等)。 另外,您可以缓存应用程序的其余资产,以确保整个应用程序也可以脱机运行。 除了主应用程序外壳之外,静态资产的这种缓存确保了PR P L模式的Pre-cache阶段。

Lines 19–38: The activate event is the place for cleaning up of unused caches.

第19–38行:Activate事件是清理未使用的缓存的地方。

Lines 40–63: These lines of code help in fetching resources from the cache if they are in cache or go to network. Also, if a network call is made, then the resource is not in cache and put into a new separate cache. This scenario helps to cache all dynamic data for an application.

第40–63行 :这些代码行有助于从缓存中获取资源(如果它们在缓存中或进入网络)。 同样,如果进行了网络调用,则资源不在缓存中,而是放入新的单独缓存中。 这种情况有助于缓存应用程序的所有动态数据。

All in all, most of the parts of the architecture have been covered. The only part left is the Lazy loading stage of the PRPL pattern. I will discuss this with regards to JavaScript.

总而言之,已经涵盖了该体系结构的大部分部分。 剩下的唯一部分是PRP L模式的延迟加载阶段。 我将就JavaScript进行讨论。

我们的构建设置 (Our Build Setup)

What is a good architectural structure without a build setup? Webpack to the rescue. There are other tools like Parcel, Rollup etc. out there, but whatever concepts we apply to Webpack can be applied to any such tool.

没有构建设置的好的建筑结构是什么? Webpack进行了救援。 还有其他工具,例如Parcel,Rollup等,但是我们应用于Webpack的任何概念都可以应用于任何此类工具。

I will map the concepts used to the plugins so that you can get hold of the basics used for setting up of the workflow. This is the most important step to getting started with a good reusable build config for your own application for the future.

我将使用的概念映射到插件,以便您掌握用于设置工作流的基础知识。 这是将来为自己的应用程序建立良好的可重用构建配置的最重要步骤。

I know how difficult it is for developers like us to configure Webpack or any tool for that matter from scratch. The following article was an inspiration which helped me to create my own build setup:

我知道对于像我们这样的开发人员从头开始配置Webpack或任何工具有多困难。 以下文章是一个启发,它帮助我创建了自己的构建设置:

A tale of Webpack 4 and how to finally configure it in the right way. Updated.

Webpack 4的故事以及如何最终以正确的方式进行配置。 更新。

Do refer to the above link if you get stuck anywhere with the build setup. For now let us check out the concepts required for the build.

如果您在构建设置中遇到任何困难,请参考上面的链接。 现在,让我们检查构建所需的概念。

ES6和动态导入支持 (ES6 & Dynamic Imports support)

Babel is a popular transpiler which is there to help us with transpiling ES6 features down to ES5. We will need the following packages to enable babel working with webpack:

Babel是一个受欢迎的转译器,可以帮助我们将ES6的功能转译为ES5。 我们将需要以下软件包来使babel与webpack一起工作:

  • @babel/core

    @ babel /核心
  • @babel/plugin-syntax-dynamic-import

    @ babel / plugin-syntax-dynamic-import
  • @babel/preset-env

    @ babel /预设环境
  • babel-core

    巴别核心
  • babel-loader

    巴别塔
  • babel-preset-env

    babel预设环境

Here is a sample babelrc for reference:

这是一个示例babelrc供参考:

During babel setup, we need to feed the following 2nd line in presets to enable babel to transpile ES6 down to ES5 and the 3rd line in plugins to enable the dynamic import support with Webpack.

在babel设置期间,我们需要在预设中提供以下第二行 ,以使babel可以将ES6向下转换为ES5,然后将第三行 插件以启用Webpack的动态导入支持。

Here is how babel is used with Webpack:

这是babel与Webpack一起使用的方式:

Lines 10–17: The babel loader is used to set up the babel transpilation process in webpack.config.js. For simplicity, the other parts of the config have been eliminated or commented out.

第10-17行 :babel loader用于在webpack.config.js中设置babel的转译过程。 为了简单起见,已删除或注释掉了配置的其他部分。

SASS和CSS支持 (SASS & CSS Support)

For setting up SASS and CSS you need the following packages:

要设置SASS和CSS,您需要以下软件包:

  • sass-loader

    萨斯装载机
  • css-loader

    CSS加载器
  • style-loader

    样式加载器
  • MiniCssExtractPlugin

    MiniCssExtractPlugin

Here is how the config looks like:

这是配置的样子:

Lines 17–25: This is the area where the loaders are registered.

第17–25行 :这是装载程序的注册区域。

Lines 29–31: Since we are using a plugin to extract a CSS file, we are using the MiniCssExtractPlugin here.

第29–31行 :由于我们使用的是插件来提取CSS文件,因此我们在此处使用的是MiniCssExtractPlugin

定制开发和生产设置 (Custom Development & Production Setup)

This is the most important section of the build process. We all know that we need a development and production build setup for developing applications and also deploying the final distributable to the web.

这是构建过程中最重要的部分。 我们都知道,我们需要开发和生产版本设置来开发应用程序,并部署最终可分发到Web的版本。

Here are the packages that will get used:

这是将要使用的软件包:

  • clean-webpack-plugin: For cleanup of the dist folder contents.

    clean-webpack-plugin :用于清理dist文件夹的内容。

  • compression-webpack-plugin: For gzipping the dist folder file contents.

    compression-webpack-plugin :用于gzip 压缩 dist文件夹的文件内容。

  • copy-webpack-plugin: For copying static assets, files or resources from application source to dist folder.

    copy-webpack-plugin :用于将静态资产,文件或资源从应用程序源复制到dist文件夹。

  • html-webpack-plugin: For creating an index.html file in the dist folder.

    html-webpack-plugin :用于在dist文件夹中创建index.html文件。

  • webpack-md5-hash: For hashing application source files in the dist folder.

    webpack-md5-hash :用于散布 dist文件夹中的应用程序源文件。

  • webpack-dev-server: For running a local development server.

    webpack-dev-server :用于运行本地开发服务器。

Here is the final Webpack config file:

这是最终的Webpack配置文件:

Lines 9–77: The entire webpack config is a function which takes two arguments. Here I have used the argv i.e., the arguments sent while running the webpack or webpack-dev-server commands.

第9–77行:整个webpack配置是一个带有两个参数的函数。 在这里,我使用了argv,即运行webpack或webpack-dev-server命令时发送的参数。

The below image shows the scripts section in package.json.

下图显示了package.json中的脚本部分。

Accordingly, if we run npm run build it will trigger a production build, and if we run npm run serve it will trigger a development flow with a local development server.

因此,如果我们运行npm run build ,它将触发生产构建,而如果我们运行npm run serve ,则将触发本地开发服务器的开发流程。

Lines 44–77: These lines show how the plugins and the development server config needs to be setup.

第44–77行 :这些行显示了如何设置插件和开发服务器配置。

Lines 59–66: These lines are any resources or static assets which need to be copied over from the application source.

第59–66行 :这些行是需要从应用程序源复制过来的任何资源或静态资产。

定制服务工作者版本 (Custom Service Worker Build)

Since we all know how tedious it is to write the names of all the files again for caching, I made a custom service worker build script for catching hold of the files in the dist folder and then adding them as contents of the cache in the service worker template. Finally, the service worker file will get written to the dist folder.

既然我们都知道再次写入所有文件的名称以进行缓存是多么乏味,所以我制作了一个定制服务工作者构建脚本来捕获dist文件夹中的文件,然后将它们作为服务中的缓存内容添加工人模板。 最后,服务工作者文件将被写入dist文件夹。

The concepts regarding the service worker file we talked about will be the same. Here is the script in action:

我们讨论的关于服务工作者文件的概念将相同。 这是运行中的脚本:

Lines 8–18: This is the place where all the contents of the dist folder are captured as an array staticAssetsCacheFiles.

第8-18行 :这是将dist文件夹的所有内容捕获为数组staticAssetsCacheFiles的地方。

Lines 22–85: This is the service worker template we talked about before. The concepts are exactly the same, just that we are introducing variables into the template so that we can reuse the service worker template and make it handy for future use. This template was also required since we needed to add dist folder contents to the cache as per line 33.

第22–85行 :这是我们之前讨论的服务人员模板。 这些概念是完全相同的,只是我们将变量引入模板中,以便我们可以重用Service Worker模板并将其方便将来使用。 由于我们需要按照第33行将 dist文件夹内容添加到缓存中,因此也需要此模板。

Lines 87–90: Finally, a new service worker file will get written to the dist folder along with its contents from the service worker template serviceWorkerScript.

第87–90行 :最后,一个新的服务工作者文件将与服务工作者模板serviceWorkerScript中的内容一起写入dist文件夹。

The command to run the above script is node build-sw and it should be run after webpack --mode production is done.

运行上述脚本的命令是node build-sw ,它应该在完成webpack --mode生产之后运行。

This service worker build script really helped me a lot in caching files easily. I am currently using this for my own side projects due to its simplicity and great ease of tackling the caching problem.

这个服务人员构建脚本确实对我轻松缓存文件有很大帮助。 由于它的简单性和轻松解决缓存问题的能力,我目前正在将其用于自己的辅助项目。

If you guys want to use a library for Progressive Web Application related features, you can go for Workbox. This library does some real neat stuff and has amazing features which you can take control of.

如果您想使用与渐进式Web应用程序相关的功能的库,可以使用Workbox 。 该库执行了一些真正的整洁的工作,并具有您可以控制的惊人功能。

最后看包装 (Final Look At The Packages)

Here is a sample package.json file with all dependencies:

这是一个带有所有依赖项的package.json文件示例:

Remember that Webpack gets updated frequently, and changes keep happening in the community with new plugins replacing existing ones. So it is important to keep a note of the concepts required for a build setup rather than the actual packages used.

请记住,Webpack经常更新,并且社区中不断发生变化,新的插件取代了现有的插件。 因此,重要的是要注意构建设置所需的概念,而不是实际使用的软件包。

JavaScript功能 (JavaScript Features)

We all have a choice: either to write our own framework for certain features to be used by our application such as change detection, routing, storage patterns, redux etc, or pull already existing packages for such features.

我们都有一个选择:要么为我们的应用程序要使用的某些功能(例如更改检测,路由,存储模式,redux等)编写我们自己的框架,要么为这些功能提取现有的软件包。

Now I’ll speak about the bare minimum features required in order to structure the layout of our application and get it going. Later on you can add your own frameworks or packages to the application.

现在,我将讨论构建应用程序布局并使之运行所需的最低限度的功能。 稍后,您可以将自己的框架或软件包添加到应用程序中。

ES6模块 (ES6 Modules)

We will use ES6 import and export statements and treat each file as an ES6 module. This feature is commonly used by popular frameworks like Angular and React and is pretty handy. With the power of our Webpack config, we can fully utilize the power of import and export statements.

我们将使用ES6导入和导出语句,并将每个文件视为ES6模块。 Angular和React等流行框架通常使用此功能,并且非常方便。 借助Webpack配置的功能,我们可以充分利用导入和导出语句的功能。

对象文字语法或ES6类语法 (Object Literal Syntax Or ES6 Class Syntax)

Building components is a very important part of our application. We can choose to go with the latest web standards like Web Components too, but to keep things simple we can go ahead and use object literal syntax or ES6 class syntax.

构建组件是我们应用程序中非常重要的一部分。 我们也可以选择使用最新的Web标准,例如Web Components,但是为了使事情简单,我们可以继续使用对象文字语法或ES6类语法。

The only thing with class syntax is that we need to instantiate it and then export it. So to keep things even simpler, I went ahead with object literal syntax for component architecture.

类语法的唯一作用是我们需要实例化然后导出它。 为了使事情变得更简单,我着手进行组件体系结构的对象文字语法。

import { appTemplate } from './app.template';
import { AppModel } from './app.model';

export const AppComponent = {

    init() {
        this.appElement = document.querySelector('#app');
        this.initEvents();
        this.render();
    },

    initEvents() {
        this.appElement.addEventListener('click', event => {
            if (event.target.className === 'btn-todo') {
                import( /* webpackChunkName: "todo" */ './todo/todo.module')
                    .then(lazyModule => {
                        lazyModule.TodoModule.init();
                    })
                    .catch(error => 'An error occurred while loading Module');
            }
        });

        document.querySelector('.banner').addEventListener('click', event => {
            event.preventDefault();
            this.render();
        });
    },

    render() {
        this.appElement.innerHTML = appTemplate(AppModel);
    }
};

Lines 4–32: We export an object called AppComponent which is immediately available for use in other parts of our application.

第4至32行:我们导出一个名为AppComponent的对象,该对象可立即在应用程序的其他部分中使用。

You can go ahead and use ES6 class syntax or standard Web Components too and achieve a more declarative way of writing code here. For simplicity’s sake, I chose to write the demo application in a more imperative approach.

您也可以继续使用ES6类语法或标准Web组件,并在此处实现更具声明性的代码编写方式。 为简单起见,我选择以一种更必要的方法编写演示应用程序。

动态导入 (Dynamic Imports)

Remember I talked about missing out on the “L” of the PRPL pattern? Dynamic import is the way to go ahead and lazy load our components or modules. Since we used the App Shell and PRPL together to cache the shell and other route assets, dynamic imports import the lazy component or module from the cache instead of the network.

还记得我谈论过错过PRPL模式的“ L”吗? 动态导入是继续加载组件或模块的方式。 由于我们将App ShellPRPL一起用于缓存外壳程序和其他路由资产,因此动态导入会从缓存而非网络中导入惰性组件或模块。

Note that if we only used App Shell architecture, the remaining assets of the application i.e., the contents of chunks folder, would not have been cached.

请注意,如果仅使用App Shell架构,则不会缓存应用程序的其余资产(即文件夹的内容)。

Lines 15–19: Refer to App Component code; this is the place where dynamic imports shine. If we click on a button having the class btn-todo, then only this TodoModule gets loaded. By the way, TodoModule is just another JavaScript file which consists of a set of object components.

第15-19行:请参阅应用组件代码; 这是动态进口大放异彩的地方。 如果我们单击具有btn-todo类的按钮则仅加载此TodoModule 。 顺便说一下, TodoModule只是另一个JavaScript文件,它由一组对象组件组成。

ES6箭头功能和ES6模板文字 (ES6 Arrow Functions & ES6 Template Literals)

Arrow functions should be used especially where we want to make sure of the this keyword inside the function, which should refer to the surrounding context where the arrow function is declared. Apart from that, these functions really help in creating neat shorthand syntax.

特别是在我们要确保函数内部的this关键字的情况下,应使用箭头函数, 关键字应引用声明箭头函数的周围上下文。 除此之外,这些功能确实有助于创建简洁的速记语法。

export const appTemplate = model => `
    <section class="app">
        <h3> ${model.title} </h3>
        <section class="button">
            <button class="btn-todo"> Todo Module </button>
        </section>
    </section>
`;

The above example is a template function defined as an arrow function which accepts a model and returns an HTML string consisting of the model data in it. String interpolation is carried out with the help of ES6 template literals. The real benefit of template literals is multi-line strings and interpolation of model data into the string.

上面的示例是一个定义为箭头函数的模板函数,该模板函数接受模型并返回其中包含模型数据HTML字符串。 字符串插值是借助ES6模板文字进行的 。 模板文字的真正好处是多行字符串和模型数据插值到字符串。

Here’s a micro tip for handling component templating and generation of reusable components: use the reduce function to accumulate all HTML strings as per the following example:

这是一个处理组件模板和生成可重用组件的微技巧:按照以下示例,使用reduce函数累积所有HTML字符串:

The above piece of code does a great deal of work indeed. Simple yet intuitive. It does follow a little inspiration from the frameworks out there.

上面的代码确实做了很多工作。 简单而直观。 它确实从那里的框架中获得了一些启发。

Lines 1–19: This is a sample model array on which the reduce function can run in order to give the reusable template feature.

第1-19行 :这是一个示例模型数组,可在其上运行reduce函数以提供可重复使用的模板功能。

Line 53: This line does all the magic in generating multiple reusable components into one HTML string. The reduce function takes in the accumulator as the first argument, and each value of the array as the second argument.

第53在将多个可重复使用的组件生成到一个HTML字符串中时,这一行发挥了所有魔力。 reduce函数将累加器作为第一个参数,并将数组的每个值作为第二个参数。

Thanks to these simple features, we already have an application structure in place. The best way to learn a feature is to put it in action they say, so here we are. ?

由于这些简单的功能,我们已经有了一个应用程序结构。 学习功能的最好方法是将其付诸实践,他们就这么说了。 ?

应用示范 (Application Demo)

Congratulations on reaching here!

恭喜您到达这里!

This post covered a lot of features indeed and getting hold of all the concepts and techniques will take some time.

这篇文章确实涵盖了很多功能,掌握所有概念和技术将需要一些时间。

Here is a demo of the to-do application built with all the features as discussed in this article. Click here to visit the site.

这是使用本文中讨论的所有功能构建的待办应用程序的演示。 单击此处访问该站点。

Click here for the link to GitHub repository. Feel free to clone the repository and go through the code for a better understanding of the conceptual examples mentioned in the article.

单击此处以链接到GitHub存储库。 随意克隆存储库并遍历代码,以更好地理解本文中提到的概念性示例。

样品制作应用 (Sample Production App)

The production site is a portfolio which was designed, developed and engineered from scratch using the exact features as specified in this article. The Single Page Application is broken down into custom modules and components.

生产站点是一个投资组合,它使用本文指定的确切功能从头开始进行设计,开发和设计。 单页应用程序分为自定义模块组件

The flexibility and power that comes with Vanilla JavaScript is something unique and does help in producing some astonishing results.

Vanilla JavaScript附带的灵活性和强大功能是独特的,确实有助于产生一些惊人的结果。

Click here to go to the site. Here is the site in action:

单击此处转到该站点。 这是实际的网站:

Do visit the site to get a feel for it. The colors are not accurately produced in the demo here. The engineering put into this site produced the following results:

请访问该网站以了解它。 颜色在此演示中无法准确生成。 放入该站点的工程产生了以下结果:

Never scored a perfect 100 before in any subject. 

在任何科目上都从未获得过完美的100分。 

结论 (Conclusion)

There are several projects we might like to build using Vanilla JavaScript instead of frameworks in order to achieve certain results quickly. I wrote this article to help developers use a simple custom setup to build their future projects.

我们可能想使用Vanilla JavaScript而不是框架来构建多个项目,以便快速实现某些结果。 我写这篇文章是为了帮助开发人员使用简单的自定义设置来构建他们未来的项目。

The best part about the Vanilla framework is that developers have the freedom to shape their engineering thought patterns according to various use cases. Be it Imperative or Declarative style of programming, creating or using of latest existing features. As long as we produce consistent and performant applications with good code maintainability, our job is done for the day.

Vanilla框架的最好之处在于,开发人员可以根据各种用例自由设计其工程思维模式。 编程,创建或使用最新现有功能的命令式或声明式样式。 只要我们生成具有良好代码可维护性的一致且高性能的应用程序,我们的工作就会一天完成。

Happy hacking! 

骇客入侵! 

Find me at https://medium.com/@anurag.majumdar

https://medium.com/@anurag.majumdar找到我

➥网站开发 (➥ Web Development)

➥生活事件 (➥ Life Event)

翻译自: https://www.freecodecamp.org/news/how-to-write-simple-modern-javascript-apps-with-webpack-and-progressive-web-techniques-a30354eab214/

webpack插件编写

 类似资料: