精华内容
下载资源
问答
  • javascript渐进增强与平稳退化浅谈
  • 本文讲的是使用 React.js 的渐进式 Web 应用程序:第 4 部分 - 渐进增强渐进增强 (Progressive Enhancement) 渐进增强 (Progressive Enhancement) 意味着所有人都可以在任意一款浏览器中访问页面的基本内容和...
    本文讲的是使用 React.js 的渐进式 Web 应用程序:第 4 部分 - 渐进增强,

    渐进增强 (Progressive Enhancement)

    渐进增强 (Progressive Enhancement) 意味着所有人都可以在任意一款浏览器中访问页面的基本内容和功能,在那些不支持某些特性的浏览器中访问时,体验上有所退化但仍然是可用的。 - Lighthouse

    一个比较完善的 Web 应用要对它所面对的市场的大部分用户是可用的。如此,如果一个 Web 应用遵循弹性开发的理念,那么它可以避免用户在第一次进入应用时遭受好几秒的白屏而非正常要展示的内容的情况:

    这是一份 ReactHN 的渲染策略 比较。在服务器端渲染 HTML 对于内容比较重要的网站是很有意义的,但相应的也会付出一系列的代价 —— 在用户多次访问 Web 应用的时候,基于 application shell 架构,已经在本地缓存的客户端渲染应用性能会更好,而服务端渲染每次都需要重新下载。我们在做抉择的时候,谨记什么是对我们更有意义的!

    Aaron Gustafson,Web 标准的布道师,将 渐进增强 比作为花生糖。花生就是网站的内容,巧克力涂层就是你的表现层,JavaScript 就是这层硬硬的糖壳。这个涂层的颜色可能会不同,体验上也会因为所用的浏览器特性不同而有所差异。

    仔细想想,这个糖壳就是很多渐进增加的特性发挥作用的地方。 他们将 web 和 原生应用的优势结合在一起。不需要安装什么东西,这对在浏览器中第一次访问这个应用的用户很有用。用户用的越多,这层糖果壳就更甜,体验就越好。

    如果你的 Web 应用是渐进增强的,即在脚本没有加载的时候也有基本的内容,Lighthouse 将给你指路。

    在我看来,渐进增强不仅仅是 让网站在没有禁用 JavaScript 脚本的条件下正常工作,也不是所谓的 SEO,而是在那种 假连 的和经常掉线的网络条件下,用户也能用上一些有用的功能。用 JavaScript 的库或者框架来实现渐进增强的话, 服务端渲染是一种有用的手段。

    统一渲染(Universal rendering)

    那么,话说回来,什么是 服务端渲染 SSR?现代 Web 应用通常是在客户端使用 JavaScript 来呈现其大部分或全部内容。 这意味着,首次渲染不仅会被下载 HTML 文件(及其依赖的 JS 和 CSS)阻塞,而且会在执行 JavaScript 代码时被阻塞。使用 SSR,让页面的初始内容在服务器上生成,这样的话浏览器可以直接获取已经存在HTML内容的页面。

    统一 JavaScript (Universal JavaScript) 就是在服务器端用 JavaScript 里的模板渲染,然后把它作为完整的 HTML 输出到浏览器。然后在客户端上,JavaScript 可以接管页面来处理页面交互。这种方式能有效地使服务器和客户端上的代码共享,在 React 中,我们一种方式实现服务器端渲染,给我们 “自由” 渐进增强。

    这个概念在React社区 流行 有下面几个原因:应用程序可以以更快的速度在页面上呈现内容,没有网络太差这个大瓶颈;即使 JavaScript 无法加载,他也会正常工作;它使得客户端代码逐步生效,以达到更好的交互体验。

    因为 renderToString 函数 (这个函数将组件渲染成初始 HTML) ,React 做统一渲染相对很自然, 虽然要达到这一点还有不少步骤要完成。 关于怎样设置SSR 有一些 指南 ,下文我们会简要阐述其中一个。

    注:统一路由(Universal routing)指从客户端和服务端都可以用同一路由找到对应的视图( React Router支持这个很好。统一数据(Universal data)获取指从客户端和服务端都可以访问数据,比如通过一个 API。我使用isomorphic-fetch(基于Fetch API polyfill)去做这件事。

    渐进式Web应用程序 Selio 中如果网络加载需要一定时间, 统一渲染会先加载一个不需 JS 即可运行的静态的版本,静态文件可以被脚本接管,以改善体验。

    具体到Application Shell 架构,您可以使用统一渲染在服务器上呈现您 Shell,以及那些你认为对用户很重要的内容 (比如文章正文),你将会自然而然的选择使用这种服务器端渲染。

    其他 PWA,如 Housing,Flipkart 和 AliExpress 服务器渲染的 shell 与 屏幕,虽然实际可能并不是立即加载,但用户会觉得内容是立即加载的。这让用户能够感觉到性能的提升。

    注意:服务器渲染可以意味着你的服务端要做 更多的工作 ,并可能会增加您的代码库的复杂性,因为您的 React 组件需要 Node 环境是可用的。 在决定是否使用 SSR 的时候,请记住这一点。 德文林赛有一个很棒的演讲在SSR perf with React,非常值得去观看!

    前面的理论知识已经够用了,我们来具体看看代码吧!

    用 React Router 的统一渲染(Universal Rendering with React Router)

    Pro React(Cassio Zen 著作)中有一个关于 Isomorphic JS 与 React 的精彩章节,我建议你读一下他。本文这一节就是基于这一章节实现的一个简化版本。

    React已经使用 ReactDOMServer.renderToString() 对服务器渲染组件提供了支持。 给定一个组件,它将生成要发送到浏览器的HTML标记。 React使用这些标记,并使用 ReactDOM.render() 加强它,监听事件来实现交互并渲染出一些内容。

    假想我们来实现一个第三方的 Hacker News 应用,使用 Express 渲染 React 组件可能看起来像这样:

    // server.js
    import express from 'express';
    import React from 'react';
    import fs from 'fs';
    import { renderToString } from 'react-dom/server';
    import HackerNewsApp from './app/HackerNewsApp';
    
    const app = express();
    app.set('views', './');
    app.set('view engine', 'ejs');
    app.use(express.static(__dirname + '/public'));
    
    const stories = JSON.parse(fs.readFileSync(__dirname + '/public/stories.json', 'utf8'));
    const HackerNewsFactory = React.createFactory(HackerNewsApp);
    
    app.get('/', (request, response) => {
      const instanceOfComponent = HackerNewsFactory({ data: stories });
      response.render('index', {
          content: renderToString(instanceOfComponent)
      });
    });

    统一渲染(Universal mounting)

    与服务器渲染组件一起渲染 React 工作,需要我们 在客户端和服务器上提供相同的 props,否则 React将无法选择,只能重新渲染 DOM,你会感觉 React 在抱怨你的这个愚蠢写法。它还将对感知的用户体验产生影响。 但问题是:我们如何使服务器作为 props 传递的数据也可在客户端上使用,然后把它作为 props 传播?一个常见的模式是将所有需要的 props 放到我们主 HTML 文件的一个 script 标签中,这样我们的客户端 JS 就可以直接使用了。 我们将其称为 “启动数据” 或 “初始数据”。

    下面是使用 EJS 模板的索引页面的示例,其中一个脚本具有我们的 React 组件所需的初始数据(initial data) 和props,另一个脚本包含我们的 React 应用程序包的其余部分。

    <!index.html →
    div id=”container”><%- content %></div>
    <script type=”application/json” id=”bootupData”>
     <% reactBootupData %>
    </script>
    <script src=bundle.js></script>

    在我们的 Express 代码中,我们可以配置我们的启动配置数据如下:

    // ...
    const stories = JSON.parse(fs.readFileSync(__dirname + '/public/stories.json', 'utf8'));
    const HackerNewsFactory = React.createFactory(HackerNewsApp);
    
    app.get('/', (request, response) => {
      const instanceOfComponent = HackerNewsFactory({ data: stories });
      response.render('index', {
          reactBootupData: JSON.stringify(stories),
          content: renderToString(instanceOfComponent)
      });
    });

    现在我们回到客户端。将相同的 props 传递给我们的客户端无疑是重要的,如果不这么做,当我们通过服务器渲染它们时,React 将无法挂载到我们的预渲染组件。 在我们的客户端代码中,为了确保功能正常使用,我们只需要用上面的 script 标签保证初始数据可用就行了:

    import React from 'react';
    import { render } from 'react-dom';
    import HackerNewsApp from './app/HackerNewsApp';
    
    let bootupData = document.getElementById('bootupData').textContent;
    if (bootupData !== undefined) {
        bootupData = JSON.parse(bootupData);
    }
    
    render(, document.getElementById('container'));

    这使我们的客户端 React 代码能够挂载到服务器渲染的组件。

    统一的数据请求(Universal Data-fetching)

    典型的SPA将有许多路由,但是一次为我们的所有路由加载所有数据是没有意义的。 相反,我们需要通过路由的映射来告知服务当前路由的组件需要什么数据,以便我们可以准确满足需要。如果用户从一个路由过渡到另一个路由,我们还需要动态拉取数据,这意味着我们需要一个支持在客户端上拉取数据和在服务器预拉取数据的策略。

    统一数据请求的常见解决方案是使用 React对statics的支持 在每个组件上创建静态 fetchData 方法,定义它需要什么数据。此方法可以随时访问,即使组件尚未实例化,这对于预拉取工作很重要。

    下面是一个简单的组件使用静态 fetchData 方法的代码片段。我们还可以利用客户端上的componentDidMount 来检查服务器是否提供了我们的启动数据,否则我们是否需要自己获取启动数据。

    // Fetch for Node and the browser
    import fetch from 'isomorphic-fetch'; 
    // ...
    class HackerNewsApp extends Component {
        constructor() {
            super(...arguments);
            this.state = {
                stories: this.props.data || []
            }
        },
        componentDidMount() {
            if (!this.props.data) {
                HackerNewsApp.fetchData().then( stories => {
                    this.setState({ stories });
                })
            }
        },
        render() {
            // ...
        }
    }
    
    // ...
    HackerNewsApp.propTypes = {
        data: PropTypes.any
    }
    
    HackerNewsApp.fetchData = () => {
        return fetch('http://localhost:8080/stories.json')
        .then((response => response.json()));
    };
    
    export default HackerNewsApp;

    接下来,让我们看看在服务器上渲染路由。

    React Router自 1.0 以来支持服务器渲染。这里有一些与客户端渲染不同的东西需要添加进来考虑,例如发送 30x 响应重定向和拉取数据之前渲染。为解决这些问题,我们可以使用一些底层 API match 使得不需要同步渲染路由组件就可以将路由转换为一个要跳转到的地址。 RouterContext用于路由的异步渲染组件。

    我们还可以遍历 renderProps 来检查是否存在静态 fetchData 方法,预拉取数据并将其作为 props 传递(如果存在)。在 Express 中,我们还需要将路由的入口点从 / 更改为通配符 *,以确保用户所访问的所有路由都调用正确的回调。

    再次查看一个 server.js:

    import express from "express";
    import fs from 'fs';
    import React from 'react';
    import { renderToString } from 'react-dom/server';
    import { match, RouterContext } from 'react-router';
    import routes from './app/routes';
    
    const app = express();
    
    app.set('views', './');
    app.set('view engine', 'ejs');
    app.use(express.static(__dirname + '/public'));
    
    const stories = JSON.parse(fs.readFileSync(__dirname + '/public/stories.json', 'utf8'));
    
    // Helper function: Loop through all components in the renderProps object
    // and returns a new object with the desired key
    let getPropsFromRoute = ({routes}, componentProps) => {
      let props = {};
      let lastRoute = routes[routes.length - 1];
      routes.reduceRight((prevRoute, currRoute) => {
        componentProps.forEach(componentProp => {
          if (!props[componentProp] && currRoute.component[componentProp]) {
            props[componentProp] = currRoute.component[componentProp];
          }
        });
      }, lastRoute);
      return props;
    };
    
    let renderRoute = (response, renderProps) => {
      // Loop through renderProps object looking for ’fetchData’
      let routeProps = getPropsFromRoute(renderProps, ['fetchData']);
      if (routeProps.fetchData) {
        // If one of the components implements ’fetchData’, invoke it.
        routeProps.fetchData().then((data)=>{
          // Overwrite the react-router create element function
          // and pass the pre-fetched data as data/bootupData props
          let handleCreateElement = (Component, props) =>(
            
          );
          // Render the template with RouterContext and loaded data.
          response.render('index',{
            bootupData: JSON.stringify(data),
            content: renderToString(
              
            )
          });
        });
      } else {
        // No components in this route implements ’fetchData’.
        // Render the template with RouterContext and no bootupData.
        response.render('index',{
        bootupData: null,
        content: renderToString()
        });
      }
    };
    
    app.get('*', (request, response) => {
      match({ routes, location: request.url }, (error, redirectLocation, renderProps) => {
        if (error) {
          response.status(500).send(error.message);
        } else if (redirectLocation) {
          response.redirect(302, redirectLocation.pathname + redirectLocation.search);
        } else if (renderProps) {
          renderRoute(response, renderProps);
        } else {
          response.status(404).send('Not found');
        }
      });
    });
    
    app.listen(3000, ()=>{
      console.log("Express app listening on port 3000");
    });

    在客户端,我们需要进行类似的调整。 当我们渲染路由时,我们检查任何启动数据。 然后我们将它作为props 传递给当前路由的组件。 React Router 的 createElement 方法 用于初始化一些元素。这些元素作为props, 传给有 fetchData 方法的组件的启动数据 。

    let handleCreateElement = (Component, props) => {
        if (Component.hasOwnProperty('fetchData') {
            let bootupData = document.getElementById('bootupData').textContent;
            if (!bootupData == undefined) {
                bootupData = JSON.parse(bootupData);
            }
            return ;
        } else {
            return ;
        }
    }
    
    render((
        {routes}
    ), document.getElementById('container'))

    就这样,有很多关于使用 React 的统一渲染的知识,深入研究其他架构像 Flux 和像 Redux 的库适合。我强烈鼓励阅读一些链接,以对其他有效的模式有一个更全面的认识。

    数据流技巧(Data-flow tips)

    当在服务器上使用 React 时,不可能在 componentDidMount 中请求数据(就像在浏览器中一样)。 该代码不会被 renderToString 调用,如果它是可能的,你的异步数据请求将不会序列化,如 Jonas 在他的Isomorphic React in Real Life中指出的那样(你应该阅读)。

    对于异步数据,答案是 “它有点复杂”。 您可以设置指示正在获取用户数据的初始状态,如占位符或加载中程序图标,或尝试正确地异步提取+渲染。

    一些小提示:)

    • componentWillMount 在客户端和服务端都能被调用,并且这个调用发生在组件渲染之前,你可以在这个生命周期里面请求数据
    • 允许你在组件里面请求数据,然后在服务器渲染之前访问他。这就意味着像 Component.fetchData()(一些你会在组件里面定义的东西)会在渲染之前请求数据,这种方式也会和 React-Route 配合使用。请求在服务器上执行,然后等待,最后渲染。这与在客户端在重新渲染之前等待请求数据不同。
    • 对于 [React Router 上的异步数据流],我在 SSR 中使用了几次。您在您的顶层组件中使用一个静态 fetchData 函数,它位于服务器端,并在渲染之前调用。 感谢 React Router的match(),我们可以找回包含我们匹配的组件的所有 renderProps,并且循环遍历它们以捕获所有 fetchData 函数并在服务器上运行它们。 [ifelse](https://ifelse.io/2015/08/27/server-side-rendering-with-react-and-react-router/)也记录了包含数据获取的 React Router 的另一个 SSR 策略。
    • React Resolver 允许你在在每个组件级别定义数据需求,在客户端和服务器上处理嵌套的异步渲染。 它旨在产生纯净,无状态和易于测试的组件,详细请看 Resolving on the server
    • 你也可以在服务端使用 Redux Store 让数据变得容易管理。一种常见的方法是使用异步Action Creators 从服务器请求数据。 这可以在 componentWillMount 上调用,您可以使用 Redux reducer 存储操作中的数据,将组件连接到 Redux reducer 并触发渲染更改。 关于他们的几个想法,参见这个的Reddit线程。 Static也由Redux推荐,如果使用 React Route, “您可能还想把您的数据获取依赖作为静态 fetchData()方法作为路由处理组件。 他们可能返回异步动作,所以你的handleRender 函数可以匹配路由到路由处理程序组件类,dispatch fetchData() 之后产生结果,并只有在 Promises resolved 之后才渲染。
    • 异步 Props提供在屏幕加载之前获取它的本地数据。它还支持在服务器上工作
    • Heroku 的 React Refetch 是另外一个试图帮助这个领域的项目。它将组件包装在 connect() 装饰器中,而不是映射state到 props,它将 props 映射到 URL(允许组件是无状态的)

    警惕使用全局变量(Guarding against globals)

    当统一渲染时,我们还需要记住,该节点没有 document 或 window 来使用。 react-dom似乎解决了这个问题,但如果你使用依赖 document, window 等的第三方组件,你需要封装或保护。

    如果依赖于 Web Storage 等这些浏览器 API,这可能会使您的代码受限。在 ReactHN 中,我们最终如下:

    // Deserialize caches from sessionStorage
    loadSession() {
     if (typeof window === 'undefined') return
     idCache = parseJSON(window.sessionStorage.idCache, {})
     itemCache = parseJSON(window.sessionStorage.itemCache, {})
    }
    
    // Serialize caches to sessionStorage as JSON
    saveSession() {
     if (typeof window === 'undefined') return
     window.sessionStorage.idCache = JSON.stringify(idCache)
     window.sessionStorage.itemCache = JSON.stringify(itemCache)
    }

    注意:虽然上面是一个合理的方法,一个更好的方法是使用 package.json 中 的 “browser” 这个属性, 然后利用 Webpack 使用这些信息自动生成浏览器与节点的版本。实际上,这意味着创建一个 “component.js” 和 “component-browser.js”,并包含一个 browser 属性,如下

          "browser": {
            "/path/to/component.js": "/path/to/component-browser.js"
          }

    这是看上去是挺好的,因为没有冗余的代码,Node 发送到浏览器,如果你做代码覆盖测试,没有必要在所有地方添加 ignore 语句。

    谨记:交互是关键(Remember: interactivity is key)

    服务器渲染很像给用户一个热苹果派。 它看起来准备好了,但这并不意味他们马上可以吃。

    渐进式的渲染如上图所示

    我们的用户界面可能包含按钮,链接和表格,由于需要的 JS 可能没有加载,在一些场景下点击按钮的时候可能不会产生任何效果。 可以以 layers 的形式为这些功能提供基本体验。一个解决这个问题的比较前瞻性的方法可能通过渐进渲染和启动的方式来聚集在交互上

    这意味着您可以在 HTML 中为包括 JS 和 CSS 的路由发送功能上可行但最小的视图。 随着更多的资源到达,应用程序逐步解锁更多的功能。 我们在[第2部分]中讨论了这个概念和实现它的模式PRPL

    实践:ReactHN(Practical implementation: ReactHN)

    没有 JS,链接指向是这样的:/story/:id,有 JS 的情况下,链接的指向是这样的:#/story/:id

    ReactHN通过提供我们的主页和评论页面的服务器端渲染解决了PE。 可以使用常规锚标签在这两个之间导航。 当加载路由的 JavaScript 时,它将接管页面,所有后续导航将使用 SPA 样式模型进行导航 - 使用 JS 提取内容,并利用已使用Service Worker 缓存的应用程序 shell。 由于基于路由的分块,我们的下一个版本还确保ReactHN变得很快交互。

    一些其他我们需要学习的东西:

    • **在服务器和客户端的PWA之间寻求100%的平衡是没有必要的。**在 React HN 中,我们注意到两个最受欢迎的页面是故事和评论。 我们为这两个部分实现了服务器渲染,其他像用户主页这样的访问量小的页面,就完全用客户端渲染。如用户配置文件。 当我们使用 Service Worker 缓存它们时,他们仍然可以立即加载重复访问。
    • 留下一些功能(明智的)。我们的客户端评论页面可以实时更新,用黄色突出显示新发布的评论。这样把这部分 JS 留在服务器上更有意义。

    测试渐进式增强(Testing Progressive Enhancement)

    Chrome DevTools 支持通过“设置”面板设置网络限制和禁用JS

    尽管现代调试工具(如Chrome DevTools)支持直接禁用 JavaScript,但我强烈建议使用 网络限制进行测试。 这更好地反映了用户多长时间后能看到您的渐进式增强应用并开始交互。 它还提供了一个视图来观测加载最小启动路由功能带来的影响,服务端渲染实现的性能等等。





    原文发布时间为:2016年11月22日

    本文来自云栖社区合作伙伴掘金,了解相关信息可以关注掘金网站。
    展开全文
  • 所谓“渐进增强”就是用一些额外的信息层去包裹原始数据。按照“渐进 增强”原则创建出来的网页几乎(如果不是“全部”的话)都符合“平稳退 化”原则。

    所谓“渐进增强”就是用一些额外的信息层去包裹原始数据。按照“渐进 增强”原则创建出来的网页几乎(如果不是“全部”的话)都符合“平稳退 化”原则。






    参考目录

    绝大多数内容来自于:JavaScript DOM编程艺术 (第2版) 作者:作者:[英] Jeremy Keith [加] Jeffrey Sambells 著 译者:杨涛 王建桥 杨晓云 等(第 5 章 最佳实践)

    展开全文
  • 什么是渐进增强by Praveen Dubey 通过Praveen Dubey 什么是渐进增强,为何如此重要 (What is Progressive Enhancement, and why it matters) Progressive Enhancement (PE) is a powerful methodology for ...

    什么是渐进增强

    by Praveen Dubey

    通过Praveen Dubey

    什么是渐进增强,为何如此重要 (What is Progressive Enhancement, and why it matters)

    Progressive Enhancement (PE) is a powerful methodology for developing web applications.

    渐进增强(PE)是用于开发Web应用程序的强大方法。

    Here is a formal definition:

    这是一个正式定义:

    Progressive enhancement is a strategy for web design that emphasizes core web page content first. This strategy then progressively adds more nuanced and technically rigorous layers of presentation and features on top of the content as the end-user’s browser/Internet connection allow. — Wikipedia

    渐进增强是Web设计的一种策略,它首先强调核心网页内容。 然后,此策略会在最终用户的浏览器/ Internet连接允许的情况下,在内容之上逐步添加更细致和技术严格的表示和功能层。 —维基百科

    The proposed benefits of this strategy are that it allows everyone to access the basic content and functionality of a web page, using any browser or Internet connection, while also providing an enhanced version of the page to those with more advanced browser software or greater bandwidth.

    此策略的建议优点是,它允许每个人使用任何浏览器或Internet连接访问网页的基本内容和功能,同时还为使用更高级的浏览器软件或更大带宽的用户提供网页的增强版本。

    And in a nutshell…

    简而言之...

    …it gives us basic user experience and cross compatibility across browsers to ensure stability.

    …它为我们提供了基本的用户体验以及跨浏览器的交叉兼容性,以确保稳定性。

    let PE = "Progressive Enhancement";

    The PE strategy consists of the following core principles:

    PE策略包括以下核心原则

    • Basic content should be accessible to all web browsers

      基本内容应可供所有Web浏览器访问

    • Basic functionality should be accessible to all web browsers

      所有网络浏览器都应可以访问基本功能

    • Sparse, semantic markup contains all content

      稀疏,语义标记包含所有内容
    • Enhanced layout is provided by externally linked CSS

      外部链接CSS提供了增强的布局
    • Enhanced behavior is provided by unobtrusive, externally linked JavaScript

      简洁的外部链接JavaScript提供了增强的行为
    • End-user web browser preferences are respected

      尊重最终用户的Web浏览器首选项

    So when you build your next website with next-generation JavaScript / CSS frameworks which work only in the most favorable environment for your code and it breaks when it does not get it…. this is not a Progressive Enhancement strategy.

    因此,当您使用下一代JavaScript / CSS框架构建下一个网站时,该框架仅在最适合您代码的环境中工作 ,而在无法获取代码的情况下便会崩溃……。 这不是渐进增强策略。

    Instead, have a goal where development should start with providing basic features, stability across all browsers and devices, and a seamless experience to the user before introducing complexity.

    取而代之的是,开发应该从提供基本功能,跨所有浏览器和设备的稳定性以及在引入复杂性之前为用户提供无缝体验开始。

    PE实例 (PE Examples)

    Let’s look at some of the examples which show how the PE strategy works.

    让我们看一些显示PE策略如何工作的示例。

    网络字体 (Web Fonts)

    Web fonts are amazing and beautiful, but when the user is on a slow network with a heavy site, they surely degrades the user experience. Even in this situation, System font should be used as the fallback to render content and can be changed to a web font as and when they are loaded.

    Web字体令人叹为观止,而且美观,但是当用户使用慢速网络访问繁重站点时,它们肯定会降低用户体验。 即使在这种情况下,也应使用系统字体作为后退来呈现内容,并且可以在加载时将其更改为Web字体。

    Showing content is better than waiting for web fonts — or getting nothing.

    显示内容比等待Web字体好-什么也没做。

    初始HTML (Initial HTML)

    Sites are loaded with script. It could be Angular, React or some other framework. When these scripts are responsible for initial content display, your user will be seeing the blank page on the browser or device when something went wrong with scripts or when the user is on the slow network.

    网站已加载脚本。 它可以是Angular,React或其他框架。 当这些脚本负责初始内容显示时,如果脚本出现问题或用户处在缓慢的网络中,则用户将在浏览器或设备上看到空白页。

    It’s always good to consider loading initial content from HTML to provide a better user experience, rather than completely relying on scripts which are yet to load.

    考虑从HTML加载初始内容以提供更好的用户体验,而不是完全依赖尚未加载的脚本,始终是一件好事。

    功能检查 (Feature Check)

    Good sites always does this part. When using a feature which is not supported based on different browsers or devices, always make sure to check if feature is available in the browser before using it in your JavaScript.

    好的网站总是在做这部分。 当使用不同的浏览器或设备不支持的功能时,请始终确保在JavaScript中使用该功能之前,先检查该浏览器是否可用。

    Modernizr is one popular library for feature detection which can help you.

    Modernizr是一个流行的功能检测库,可以为您提供帮助。

    You can load additional scripts to load fallback support only when it’s not available in the browser or device. This way you can avoid loading extra scripts when they are not required.

    仅当浏览器或设备中不提供后备支持时,您才能加载其他脚本以加载后备支持。 这样,您可以避免在不需要额外脚本时加载它们。

    现在,为什么要使用PE? (Now, Why PE ?)

    Important reasons to focus on the PE strategy before building your next application:

    在构建下一个应用程序之前,专注于PE策略的重要原因:

    强大的基础 (Strong Foundation)

    PE focuses on the start of your project using only the very basic web technologies before introducing some of the very complex features. So in all cases, you have the foundation to back your complex features to make sure they work.

    在介绍一些非常复杂的功能之前,PE专注于仅使用最基本的Web技术启动项目。 因此,在所有情况下,您都具有支持复杂功能以确保它们起作用的基础。

    Once the team is confident that the core-experience of the site is stable, and will work without heavily relying on network speed, browser, and device, then you can start introducing layers of more complex features or sci-fi stuff.

    一旦团队确信站点的核心体验是稳定的,并且可以在不严重依赖网络速度,浏览器和设备的情况下工作,那么您就可以开始引入更复杂的功能或科幻内容了。

    稳定性 (Stability)

    Quality Team : “ Search Icon is not working in Safari for Offers page ”

    Quality Team :“搜索图标在Safari的“优惠”页面中不起作用”

    Dev Team : “ Well it works on my machine, clear cache, reload or die ”

    Dev Team :“它可以在我的机器上正常工作,清除缓存,重新加载或消失”

    Quality Team (from heaven) : “ Still does not work, you are checking on Chrome, it’s breaking on Safari ”

    Quality Team (来自天堂):“仍然无法正常工作,您正在使用Chrome进行检查,但在Safari上却无法使用”

    Dev Team : “ When did we start supporting Safari ? wait…. patching patching………”

    Dev Team :“我们何时开始支持Safari? 等待…。 修补…………”

    if(getBrowsers() == 'safari') {
    Patch.magicHelpers.searchIconMagic()
    }
    Patch.magicHelpers = {
    searchIconMagic: function() {
    // Can't share magic, doing something
    }};

    “after 1 hour…… check now ”.

    “一小时后……现在检查”。

    Quality Team: “ Working fine for Chrome and Safari but broke for Mozilla now…Ahhhhh !!!!!”

    Quality Team :“在Chrome和Safari上可以正常工作,但现在在Mozilla上可以使用了……嗯!!!!”

    Well, we all have been in this situation at least once.

    好吧,我们所有人都至少遇到过一次这种情况。

    Cost for Stability and Maintenance of a project also depends on how the project starts. Setting up a project with frameworks and patching it will not work for the long term.

    项目的稳定性和维护成本还取决于项目的开始方式。 从长远来看,使用框架设置项目并对其进行修补是行不通的。

    The PE strategy helps you build a strong foundation for your project where your HTML, CSS, and JS are aligned and aim to provide fallbacks. They try to make sure you’re not heavily relying only on browser specific features.

    PE策略可帮助您为HTML,CSS和JS保持一致并旨在提供后备项目的项目打下坚实的基础。 他们试图确保您不会严重依赖浏览器特定的功能。

    SEO和可访问性 (SEO and Accessibility)

    Everyone wants to get their application listed in the first page of the search engine, but it takes consistent work and planning to build such amazing applications. The strong foundation for your project makes sure your application is focusing on the content-first approach.

    每个人都希望将他们的应用程序列在搜索引擎的第一页中,但是要构建如此出色的应用程序,需要进行一致的工作和计划 。 项目的坚实基础确保您的应用程序专注于内容优先的方法。

    Pages built with the PE strategy make sure basic content is always accessible for the search engine spider and is ready to be indexed. Avoid any dynamic content rendering that may hinder the spider crawling your content.

    使用PE策略构建的页面可确保搜索引擎蜘蛛始终可以访问基本内容 ,并可以对其进行索引。 避免任何可能阻碍蜘蛛爬网内容的动态内容呈现。

    Progressive Web Apps (PWA) are made to work for all users, regardless of their browser choice, because they’re built with progressive enhancement as a core principle.

    渐进式Web应用 (PWA)适用于所有用户,无论他们使用何种浏览器,都是因为它们以渐进式增强为核心原理而构建。

    总结思想 (Closing thoughts)

    The PE strategy focuses on a strong foundation for your project. This strong foundation helps you in your vision for your product for a long term plan.

    PE策略专注于为您的项目打下坚实的基础。 强大的基础可以帮助您制定长期计划的产品愿景。

    It’s easy to hook into a new JavaScript / CSS framework for your new project and start coding, but that may lead to Graceful Degradation. You will keep on patching your code with fallbacks for browsers or devices which do not support frameworks.

    可以很容易地为您的新项目挂接到新JavaScript / CSS框架并开始编码,但这可能会导致Graceful Degradation。 对于不支持框架的浏览器或设备,您将继续使用备用代码来修补代码。

    Although the PE strategy takes a bit more planning in the initial stages, it makes sure your user is able to experience at least basic functionality in the worst case also. PE is not workable in situations that rely heavily on JavaScript to achieve certain user interface presentations or behavior, but for a long-term project, it’s worth considering certain aspects of PE strategy.

    尽管PE策略在初始阶段需要进行更多规划,但它可以确保您的用户在最坏的情况下也能够至少体验基本功能。 PE在严重依赖JavaScript来实现某些用户界面表示或行为的情况下不可行,但是对于一个长期项目,值得考虑PE策略的某些方面。

    Hopes this gave an overview of the Progressive Enhancement Strategy.

    希望这能概述渐进增强策略。

    Feel free to drop a comment below.

    随时在下面发表评论。

    Thank you for reading this article! If you have any questions, send me an email (praveend806 [at] gmail [dot] com).

    感谢您阅读本文! 如果您有任何疑问,请给我发送电子邮件(praveend806 [at] gmail [dot] com)。

    Resources which talk about more about PE and case studies:

    有关PE和案例研究的资源更多:

    Designing with Progressive Enhancement: Building the Web that Works for EveryoneProgressive enhancement is an approach to web development that aims to deliver the best possible experience to the…www.oreilly.comUnboring.net | Workflow: Applying Progressive Enhancement on a WebVR projectHow I made an interactive content to be embedded on weather.comunboring.net

    渐进式增强功能设计:构建适合所有人的Web 渐进式增强功能是一种Web开发方法,旨在向……提供最佳体验 。www.oreilly.com Unboring.net | 工作流程:在WebVR项目上应用渐进增强功能 如何将交互式内容嵌入到weather.com上 unboring.net

    翻译自: https://www.freecodecamp.org/news/what-is-progressive-enhancement-and-why-it-matters-e80c7aaf834a/

    什么是渐进增强

    展开全文
  • 网页制作Webjx文章简介:如果你挠着头想弄清楚优雅降级和渐进增强的区别,我告诉你,这是视角问题。优雅降级和渐进增强都考虑网站在各种设备的各种浏览器上如何良好运转。两者区别的关键在于它们各自关注的焦点,...
  • 渐进增强

    2015-10-09 00:35:39
    渐进增强方案并不假定所有用户都支持javascript,而总是提供一种候补方法,确保用户可以访问(主要的)内容。 使用渐进增强时,无需为了一个已成型的网站在旧式浏览器下正常工作而做逆向工程。首先,只需要为所有的...
    从被所有浏览器支持的基本功能开始,逐步地添加那些只有新式浏览器才支持的功能。渐进增强是值得所有开发者采用的做法。渐进增强方案并不假定所有用户都支持javascript,而总是提供一种候补方法,确保用户可以访问(主要的)内容。
    使用渐进增强时,无需为了一个已成型的网站在旧式浏览器下正常工作而做逆向工程。首先,只需要为所有的设备和浏览器准备好清晰且语义化的HTML以及完善的内容,然后再以无侵入(unobtrusive)的方式向页面增加无害于基础浏览器的额外样式和功能。当浏览器升级时,它们会自动地呈现出来并发挥作用。
    想让网站在任何环境下看起来都保持一致是不可能的,不管为此付出多少努力,结局依旧会令你失望。与其试图让IE看起来堪比年轻它十岁的浏览器,不如努力改善网站的可访问性,或是进行更多的可用性测试,而不仅仅是让页面看起来更靓一点。
    某些CSS3特性在不支持它的浏览器中简直是无法模拟实现的,但若使用渐进增强,就无需为了能让你的网站适合所有人而放弃这些技术。仅仅因为部分人不愿或不能升级浏览器,却让使用新型浏览器的用户无法享受CSS3所提供的伟大技术,这是毫无道理可言的。
    我们应该先让网站能够正常工作于尽可能旧的浏览器上,然后不断为它在新型浏览器上实现更多的增强和改进。随着时间的推移,当越来越多的人开始升级浏览器而浏览器本身的支持度也不断提升时,就会有越来越多的人体验到这些增强和改进,它持续有效的使网站越来越好,却如需你刻意做什么。
    展开全文
  • 找了一上午 ,终于找到了,什么优雅降级,什么 渐进增强,就一个意思么,为了实现css3的特效和js之间的配合实现设计效果。 不过话是这么说的 但是这个东西思路还是有些不一样 优雅降级:在网站设计时,术语优雅降级...
  • 浅尝 javascript 平稳退化和渐进增强 何为平稳退化?何为渐进增强?下面举例说明: 例如,有的早期的纯文本浏览器中不支持在html里包含图片,相应是使用alt属性的替代文本。 而现在的浏览器也仍有功能较弱的,...
  • 具有通用JavaScript渐进增强功能的待办事项列表 此示例应用程序使用“通用” JavaScript在服务器和客户端上呈现HTML。 它使用Node.js, , 和进行渲染和UI逻辑。 为了将待办事项存储在服务器上,它使用键值数据库 ...
  • 渐进增强,就一个意思么,为了实现css3的特效和js之间的配合实现设计效果。 不过话是这么说的 但是这个东西思路还是有些不一样 优雅降级:在网站设计时,术语优雅降级指的是新的或者是复杂特点的明智实施,...
  • 在google.com.hk的左上角,有一个更多的链接,它具有一个目标地址,但是当我们点击时,大多数情况发现的是弹出一个下拉列表供用户选择(这是一种典型的渐进增强形式)。怎么理解?——如果用户的浏览器支持...
  •  javascript平稳退化就是如果一个浏览器完全不支持js或者禁用js的时候,它的基本功能不会受到任何影响。比方说一个网站使用了大量javascript来优化页面,我们现在把浏览器的javascript给禁用掉,这个网站的显示效果...
  • 渐进增强与优雅降级你可能听过优雅降级(graceful degradation)和渐进增强(progressive enhancement)这两个词,它们是构建Web应用时,处理多浏览器支持的两种方法论,并在Web社区中引发过激烈的辩论。持优雅降级...
  • 渐进增强 && 优雅降级

    2019-04-17 14:10:37
    渐进增强(Progressive Enhancement)和优雅降级(Graceful Degradation)是前端开发中很重要的两个概念,尽管也许你没有听过,但是实际开发中肯定已经接触到了,当然面试也经常会问到。 起因 之所以会出现渐进...
  • 什么是渐进增强

    千次阅读 2017-05-05 18:46:42
    渐进增强是指在 web 设计时强调可访问性、语义化 HTML 标签、外部样式表和脚本。保证所有人都能访问页面的基本内容和功能,同时为高级浏览器和高带宽用户提供更好的用户体验。核心原则如下: 所有浏览器都必须能访问...
  • 1.渐进增强和优雅降级都是一种开发方式,更是一种设计理念。 2.渐进增强是指在编写Web页面时,首先保证最基本、最核心的功能实现,并让所有的浏览器(包括旧式、低端的浏览器)都能看到站点的内容;然后再考虑使用...
  • 什么是平稳退化:如果正确地使用了JavaScript脚本,就可以让访问者在他们的浏览器不支持js的情况下仍然能顺利地浏览该网站。就是说,虽然某些功能无法使用,但是最基本地操作仍能顺利完成。
  • 平稳退化 渐进增强

    2017-03-28 23:55:21
    我们要知道,网站的访问者完全有可能使用的是不支持JavaScript的浏览器,还有一种可能就是浏览器支持,但是用户可能因为不想看到弹出广告而禁用了JavaScript,所以,我们应该考虑,面对这些用户的时候要怎样解决他们...
  • 优雅降级和渐进增强

    2019-07-29 20:09:23
    优雅降级和渐进增强 优雅降级: 从一开始就构建完整功能,然后针对浏览器进行恢复和测试。 渐进增强: 一开始就针对低版本浏览器进行页面的构建,完成基本的功能,然后再对高版本浏览器进行追加,交互,效果等,已...
  • 渐进增强模型

    2017-12-19 20:27:23
    在网页设计者的社区总流传着一条于强调内容重要性的 指导原则-----渐进增强  无论项目大小,我们都应该遵守这条原则。    
  • css动画设置渐进渐出An earlier article on this site demonstrated how to use the HTML5 <dialog> element to create easy “lightbox” UI. A few of my web development students are trying to take the ...
  • 优雅降级 与 渐进增强

    千次阅读 2016-09-05 21:37:12
    优雅降级与渐进增强 何为渐进增强、优雅降级? 通过使用某些技术,当浏览器支持相应功能时文档会得到增强(渐进增强),而当浏览器不支持相应功能时,文档被退化(优雅降级)。但不支持相应功能的浏览器也会...
  • 示例 1 渐进增强,同构 Node.js 与 React.js Web 应用程序示例
  • 平稳退化和渐进增强

    2018-02-28 12:19:08
    平稳退化:确保网页在没有javascript的情况下也能正常工作。也就是说,虽然某些功能无法使用,但最...渐进增强:就是用一些额外的信息层去包裹原始数据。按照渐进增强原则创建出来的网页几乎都符合平稳退化的原则。...
  • 渐进增强和优雅降级

    2021-03-03 09:52:10
    渐进增强 :针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验。 优雅降级 :一开始就构建完整的功能,然后再针对低版本浏览器进行兼容 .....
  • 元素的自动渐进增强 安装 npm install formium --save 用法 Formium是一种渐进的增强功能,它使您可以通过AJAX无缝提交纯旧HTML表单,并以常规方式处理响应。 formium.submit(form, done?) 就像您期望的那样,此...
  • 平稳退化 :确保网页在没有JavaScript的情况下也能正常的工作 网站的访问者可能是不支持JavaScript也可能是禁用了JavaScript,如果没有考虑这两种情况,这些用户访问你的网站会出新很多的问题。 所以在浏览器不...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 11,388
精华内容 4,555
关键字:

js渐进增强