当前位置:澳门新葡亰网站所有平台 > www.7415.com > 小白学react之由FOUC引发的一次webpack变革

小白学react之由FOUC引发的一次webpack变革

文章作者:www.7415.com 上传时间:2019-09-10

1. SCSS导入引发的主题材料 - FOUC之坑

后天在整治代码的时候遭受三个标题。正是初次加载页面包车型地铁时候页面会产出长时间内的闪光。也正是说,当我们第二次加载页面或然刷新首屏的时候,会在相当的短的日子内先出示一下之类页面:

home_li_flash_bef.png

能够看来地点的多个li元素依旧在未有采用上css此前的。然后十分的快的漫天页面又回形成应用上css之后的页面:

home_li_flash_aft.png

用作小白,令人相当的慢的一些是,碰着这种难点都不知底应该谷歌(Google)什么主要字!尝试过种种" reactjs first page refresh flash page reload sass import issue scss apply issue..."品级一次全国代表大会堆而无果。最后无意开采原先是叁个誉为FOUC (Fash Of Unstyled Content)的主题材料。

flash of unstyled content (FOUC, also flash of unstyled text or FOUT)[1][2] is an instance where a web page appears briefly with the browser's default styles prior to loading an external CSS stylesheet, due to the web browser engine rendering the page before all information is retrieved. The page corrects itself as soon as the style rules are loaded and applied; however, the shift may be distracting. Related problems include flash of invisible text (FOIT) and flash of faux text (FOFT).

简短来讲正是当样式表晚于结构性html 加载,当加载到此体制表时,页面将终止在此之前的渲染。此样式表被下载和剖析后,将另行渲染页面,也就出现了短短的闪光现象。

听他们讲诱因有两种:

1,使用import方法导入样式表。
2,将样式表放在页面底部
3,有多少个样式表,放在html结构的两样岗位。

而化解方法正是:

化解措施:使用LINK标签将样式表放在文书档案HEAD中

因为我们的scss的体制确实是通过import的秘诀给导入到大家的依次页面包车型客车,所以小编相信大家的诱因是第一种。以Home.jsx的样式表引进为例(上海教室中的多少个li的渲染就是在Home页面中的):

import React from 'react'
import { Link } from 'react-router'
import  './Home.scss'
import BaseLayout from "./BaseLayout.jsx";

var Home = React.createClass({

    render() {
    return (
        <BaseLayout title="Home" style={{"backgroundColor":"white"}}>
          <div >
              <nav >
                <li className="home__tab__li"><Link to="/locations" >名胜古迹</Link></li>
                <li className="home__tab__li"><Link to="/about" >关于techgogogo</Link></li>
                  <div style={{clear:"both"}}></div>
                {this.props.children}
              </nav>
          </div>
        </BaseLayout>
    )
  }
})

module.exports = Home;

那便是说依据给出去的减轻方案,大家是应该在运营的时候将scss提抽出来改成叁个单独的css文件,然后在index.html的页面模版军长其引进。

参与提抽取来的css文件叫做style.css,那么index.html的页面代码就应当改为:

<!doctype html>
<html >
  <head>
    <link rel="stylesheet" type="text/css" href="style.css" />
  </head>
  <body>
    <div id="ReactApp"></div>
  </body>
  <script src="bundle.js"></script>
</html>

这这里的标题就改为是怎么生成这么些css文件?遵照大家事先的实战,整个源码在webpack打包之后实际就独有五个bundle.js文件而已。

6. 清理废物构建文件

将文件名打开hash的同一时候,会引进一个新的主题材料:每一次当大家修改了文本后开展双重构建,因为文件内容变了,所以hash出来的文书名也必定产生更换。那么在营造多此番之后,我们的build目录下就能布满第一次全国代表大会堆充满哈希值的公文名的垃圾文件。

此刻大家很有要求在创设前将其清理掉,以维持build目录的清新干爽。

此处引进四个新的webpack插件clean-webpack-plugin,使用办法也极其轻便。

首先,大家跟过去同样将该插件给装上:

npm install clean-webpack-plugin --save-dev

下一场,我们在webpack.config.js中程导弹入该模块:

const CleanPlugin = require('clean-webpack-plugin');

最后对生产安插的plugins实行修改。因为支付情状中这一个文件都以在内部存款和储蓄器产生的,所以我们无需开展其余配置。

new CleanPlugin(['build'], {
  root: path.resolve(__dirname,"./"),
  verbose: true,
  exclude: ['template.html','logo.png']
})

其中:

  • build: 所需求清理的文本夹。就是相对下边包车型大巴root路线下的build文件夹
  • root: webpack.config.js文件所在的相对路线
  • exclue: 没有须要消除的文书列表

迄今截止,大家完毕了对任何webpack.config.js举办了极大的退换,整个项指标创设也就更像模像样了。

7. 源码

git clone https://github.com/kzlathander/alt-tutorial-webpack.git
cd alt-tutorial-webpackgit
checkout 07
npm install
npm run prod

同时

正文由世界会常德分舵编写,转发需授权,喜欢点个赞,奚弄请研究,进一步沟通请关怀自个儿天地会新乡分舵以及《微信小程序支付》主题。

《未完待续》

世界会德阳分舵注:随着微信应用号的有声有色,相信新一轮的APP变革将要发生。作为行当爱妻士,大家很应该去拥抱那么些样子。当中Reactjs相信是支付webapp的尖子,这段时日将会透过改建官方实例alt-tutorial来上学Reactjs相关的学识。

上一篇《小白学react之页面BaseLayout框架及微信的坑》大家上学了怎么着为各类Components提供三个基础的父框架组件来拍卖不相同页面包车型大巴Title的体现和Style样式的显示。

3.1 混乱的配备

但是此地难点也亲临了,大家在做项指标进程中,开垦情势和生育方式的打包进度往往是不均等的。

举个例子,大家开采情势中大家需求制定webpack-dev-server的片段参数,而在生养方式下我们是无需的。

只是大家事先将一长串的参数放到了package.json的scripts上边:

  "scripts": {
    "build": "webpack",
    "dev": "webpack-dev-server  --inline --devtool eval --host 0.0.0.0 --progress --colors --hot --content-base ./build --history-api-fallback",
    "prod": "npm run build & node server.js"
  },

实际上更规范点的做法应该是将其一大串参数放到webpack.config.js里面,举例大家位于config下边:

    devServer: {
        historyApiFallback: true,
        //hot: true,
        inline: true,
        progress: true,
        // display only errors to reduce the amount of output
        stats: 'errors-only',
        devtool: eval,
        colors: true,
        contentBase: "./build",

        // parse host and port from env so this is easy
        // to customize
        host: "0.0.0.0",// process.env.HOST,
        port: process.env.PORT
    },

那正是说那就重临了我们地点谈到的标题,那个devServer只是在开荒格局才需求的,在生养方式下是不供给的。

其中生产形式笔者这里指的是package.json的scrip下的build命令,而支出形式指的是dev命令:

  "scripts": {
    "build": "webpack",
    "dev": "webpack-dev-server 
    "prod": "npm run build & node server.js"
  },

那么大家怎么着工夫科学的将支付配置和生育布局分离开来吧?

5. Hash文件名以制止浏览器Cashe导致难题

有了上边包车型地铁html文件自动生成的体制之后,大家明天就足以将转移的js文件和css文件给hash起来了。

怎么大家必要给那个文件的公文名做哈希呢?哈希的结果本来正是每一遍更动的文件的名字都会分裂等了。可是名字分歧等又是为哪出呢?

那根本是因为要管理浏览器cache导致的文本修改未有及时起效的主题材料。

比如,我们脚下经过浏览器访谈大家的付出服务器机器的时候,会去加载bundle.js文件。那么下一次自己有新的换代,重新编写翻译之后,小编再去通过浏览器去拜见就能意识更新未有行使上。因为,那一年浏览器开掘bundle.js文件名未有变,它就能利用原本cache起来的bundle.js继续提供劳务。那,正是干吗大家供给hash文件名。

实质上hash文件名在webpack的布局中国和欧洲常简单,大家只须要用上webpack中的别的三个要害字[chunkhash]就好了。

率先,大家修改base配置下的ouput项,将原来生成的bundle.js那些文件的公文名如下:

    output: {
        filename: '[name].[chunkhash].js',
        path: path.resolve(__dirname,"build"),
    },

build后调换的文本新秀会是"app.xxxxx.js",当中xxxxx代表的便是hash。

并且,大家修改生成的css文件的文本名如下:

var extractSCSS = new ExtractTextPlugin('[name].[chunkhash].css');

那儿再运转:

npm run build

咱俩就会看出build文件夹上面会生成增加了哈希值的js和css文件,同有时候,我们会注意到index.html文件也会随着而变:

<!DOCTYPE html>
<html><head><link href="app.4f8080c8499588890c06.css" rel="stylesheet"></head>
  <head>
    <meta charset="UTF-8">
  <body>
    <div id="ReactApp"></div>
  <script type="text/javascript" src="app.4f8080c8499588890c06.js"></script></body>
</html>

3. 分别开垦和生育铺排

2. webpack如何将scss打包成单身的css文件

为了将css打包成单身的三个文书,我们得以依赖三个叫做extract-text-webpack-plugin的webpack插件,我们能够从其github网页中查看到中央的消息以及接纳实例。

第一,大家需求将该模块安装上:

npm install extract-text-webpack-plugin --save-dev

然后大家须要在大家的webpack.config.js文件中程导弹入该模块:

let ExtractTextPlugin = require('extract-text-webpack-plugin');

随即实例化贰个对象:

var extractSCSS = new ExtractTextPlugin('[name].css');

在意这里的[name]是webpack上面的贰人命关天字,代表entry中的块(chunk)的键。比如我们的entry的概念如下:

    entry: {
        app: path.resolve(__dirname, 'src/App.jsx'),
    },

那正是说那么些[name]正是此处的“app”。缺省的话会是“main”。

接下来我们要求在plugins中投入这么些实例:

 plugins: [
        new OpenBrowserPlugin({ url: 'http://localhost:8080' }),
        extractSCSS,
    ]

末尾,将scss文件的loader改成如下:

{
    test: /.scss$/,
    //loaders: ["style", "css?sourceMap", "sass?sourceMap"]
    loader: extractSCSS.extract('style', 'css!sass?sourceMap'),
}

到此,大家的webpack.config.js配置文件纵然协理中校scss文件抽出成两个单身的css文件的做事了。大家在执行webpack打包的时候,那个职业就能够自行达成:

npm run build

事成之后你会发觉在build目录下活动会调换贰个叫做app.css的文书。

只是,咱们运营此前还索要做多三个政工,正是日前提到的须求将css文件放到index.html这几个模版文件的header部分:

<!doctype html>
<html >
  <head>
    <link rel="stylesheet" type="text/css" href="app.css" />
  </head>
  <body>
    <div id="ReactApp"></div>
  </body>
  <script src="bundle.js"></script>
</html>

末段我们运维下边发号施令进行李包裹装和运维express服务器:

npm run prod

开垦浏览器就能够访谈到大家熟识的页面了。那时你会发觉无论是你怎么刷新网页,再也不会现身FOUC难题了。

道理当然是那样的,你也足以在开拓格局下运营,bundle.js和app.css文件会自动在内部存款和储蓄器中变化,其功用是大同小异的:

npm run dev
  • FOUC问题
  • 生育和开拓配置分离
  • 自动生成index.html页面模版文件
  • 哈希文件名
  • 清理垃圾营造文件

关键须要缓慢解决的主题材料如下:

4. 说了算index.html页面模版文件生成

何以我们要求做这么些业务呢?因为,在此以前咱们的index.html文件是手动创设的,从前的css文件也绝非独立包装出来,那么大家明天有了单身的css文件从此,大家就须求手动的将那个css文件加到index.html文件之中了。

一经那么些css文件的名字固定的话,那么大家只是修改一遍也并未有多大标题。然而,倘使像往下就要讲到的,打包出来的这些css文件假使每回都差别样的话,那么大家是不恐怕每回都去手动更新那一个html文件的了。

为了达到那么些目标,这里我们供给html-webpack-plugin的帮组。同理,大家先把那些模块给安装上:

npm install html-webpack-plugin --save-dev

下一步正是跟着github上的品类Readme去开展示公布局了。

率先,大家须求引入那几个模块:

const HtmlWebpackPlugin = require('html-webpack-plugin');

接下来,因为大家往下的HtmlWebpackPlugin配置在生成index.html的时候必要多个模板,所以大家先将原先的index.html该名称为template.html,并修改内容如下:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
  <body>
    <div id="ReactApp"></div>
  </body>
</html>

此地我们去掉了css和bundle脚本的引进,因为这一个往下会自动生成并插入到这些模版中生成新的index.html文件。

往下一步大家就须求去在webpack.config.js文件中持续安顿该怎么着依据模版生成新的index.html文件了。

那些安排是要放置配置的plugins上的。大家那边有base的配置,production的配置和development的配备,那么,大家这里只对生产条件调节新index.html文件的成形,所以大家只需求在生育布局下进展plugins配置就好了:

if(TARGET === 'build' || TARGET === 'prod') {

    module.exports = merge(base, {
        module: {
            loaders: [
                {
                    test: /.scss$/,
                    loader: extractSCSS.extract('style', 'css!sass?sourceMap'),
                }
            ]
        },
        plugins: [
            extractSCSS,
            new HtmlWebpackPlugin({
                template: path.resolve(__dirname, "build/template.html"),
            })
        ]
    });
}

实则从该plugin的github网址上得以观望,该插件是帮助广大安插项的。因为我们那边的alt-tutorial演示项目相比较轻松,所以这里只用了template这些布局项,其余项默许。

暗中同意的话,该插件会:

  • 因而template那些设置项找到大家的template.html文件,并在内部存款和储蓄器中拷贝一份到index.html文件之中,然后针对内部存款和储蓄器中的该index.html文件实行往下的主宰
  • 将webpack生成的css文件引进到index.html的head部分
  • 将webpack生成的js文件引进到index.html的body部分
  • 保留index.html到硬盘上

于是,在大家运转上边包车型大巴通令之后:

npm run build

咱俩会发掘多少个新的index.html文件将会在build目录下转移:

<!DOCTYPE html>
<html><head><link href="app.css" rel="stylesheet"></head>
  <head>
    <meta charset="UTF-8">
  <body>
    <div id="ReactApp"></div>
  <script type="text/javascript" src="bundle.js"></script></body>
</html>

3.2. 界别打包蒙受之npm_lifecycle_event

在webpack.config.js中要将开荒配置和生育布局分离开来,首先大家就要获取到当下的景况究竟是付出依然生育。

延续祖宗门户和开荒,首假如浮未来大家跑的吩咐是 "npm run build" 依旧"npm run dev", 约等于呈现在package.json的scripts脚本的下令上。

那么我们在wepack.config.js中假设能看清到客户跑的究竟是哪位命令的话,大家就会到达那或多或少。

那时候,特殊的情形变量npm_lifecycle_event就要登上舞台了。

npm 正在进行哪个 npm script, npm_lifecycle_event 意况变量值就能够设为其值,举个例子

  • 试行 npm run dev 命令时,则其值为 "dev" ;
  • 执行 npm run build 命令时,其值为 "build" ;

故此,我们在webpack.config.js中首先须求做的就是获取到这一个变量:

const TARGET = process.env.npm_lifecycle_event;

区分别当前亟待打包的是支付条件依旧生产条件之后,大家下一步要做的正是将它们的配备代码分开。

后天自身会尝试就和睦踩到的七个坑最早,通过对webpack做越来越修改,来上学越来越高端点的webpack相关的知识点。

3.3. 布局分离之webpack-merge

配置分离大家会用到的是webpack-merge那几个包,大家先把它安装上:

npm install webpack-merge --save-dev

webpack-merge是特意用来拍卖webpack.config.js的配置文件分别的。它根本提供二个merge方法,来将种种分开的配备项给合併在联合具名,详细情形请查看github。

上面大家就足以参见其网站的演示,将支付和生育的包装配置给分离开来了,代码如下:

var path = require('path');
var OpenBrowserPlugin = require('open-browser-webpack-plugin');
const merge = require('webpack-merge');

const ExtractTextPlugin = require("extract-text-webpack-plugin");
var extractSCSS = new ExtractTextPlugin('[name].css');

const TARGET = process.env.npm_lifecycle_event;

var base = {
    entry: {
        app: path.resolve(__dirname, 'src/App.jsx'),
    },
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname,"build"),
    },

    module: {

        loaders: [
            {
                test: /.(js|jsx)$/,
                loader: 'babel',
                query: {
                    presets: ['es2015', 'react','stage-2']
                }
            }
        ]
    }
};

if(TARGET === 'dev' || !TARGET) {

    module.exports = merge(base, {
        devServer: {
            historyApiFallback: true,
            //hot: true,
            inline: true,
            progress: true,
            // display only errors to reduce the amount of output
            stats: 'errors-only',
            devtool: eval,
            colors: true,
            contentBase: "./build",

            // parse host and port from env so this is easy
            // to customize
            host: "0.0.0.0",// process.env.HOST,
            port: process.env.PORT
        },
        module: {
            loaders: [
                {
                    test: /.scss$/,
                    loaders: ["style", "css?sourceMap", "sass?sourceMap"]
                }
            ]
        },

        plugins: [
            new OpenBrowserPlugin({url: 'http://localhost:8080'}),
        ]
    });
}

if(TARGET === 'build' || TARGET === 'prod') {

    module.exports = merge(base, {
        module: {
            loaders: [
                {
                    test: /.scss$/,
                    loader: extractSCSS.extract('style', 'css!sass?sourceMap'),
                }
            ]
        },
        plugins: [
            extractSCSS
        ]
    });
}

从代码能够见到,整个经超过实际际上正是将配置文件拆分,以便能展开越来越灵活的自由组合配置。这里有几点多少提一下的是:

  • 咱俩本来是独有贰个叫作config的配备项,现在因为急需做安插分离,所以我们将该配置项改成base。意思是这是三个中坚配备,由上面包车型客车支出和生育布局后续和扩张
  • 跟随大家会咬定当前跑的是或不是是"npm run dev"命令大概是其余没有特意在package.json中钦赐的一声令下,要是是的话,就能够通过webpack-merge的merge方法,将开垦条件下打包所急需的特定配置项参预到下边包车型大巴基本配备项地方,最终将安插给export出去。
  • 往下的生产条件安顿分离和支出情状的陈设分离类似,那就相当的少说了。

配备分离化解后,大家下五个要减轻的难题便是index.html页面模版文件的扭转。

react-webpack.png

本文由澳门新葡亰网站所有平台发布于www.7415.com,转载请注明出处:小白学react之由FOUC引发的一次webpack变革

关键词: