bwin亚洲必赢5566手机版微白学react之由FOUC引发的均等蹩脚webpack变革

  • FOUC问题
  • 生育与支出配置分离
  • 自动生成index.html页面模版文件
  • 哈希文件称
  • 清理废物构建文件

根本要解决的题材如下:

7. 源码

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

同时

本文由世界会济宁分舵编写,转载需授权,喜欢点单赞,吐槽要评论,进一步沟通请关注本身天地会潮州分舵以及《微信小程序支付》主题。

《未完待续》

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文件而已。

今自己会尝试就是好踩到之一个坑开端,通过对webpack进行更加的改,来读还高级点的webpack相关的知识点。

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进行了相比特另外变动,整个项目标构建也便再也像模像样了。

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;

区分别时急需打包的凡付出条件依旧生产条件后,大家下一致步要做的即便是将它们的布代码分开。

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

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>

react-webpack.png

天地会柳州分舵注:随着微信应用号的呼之欲出,相信新一轮的APP变革将有。作为行业内人员,我们万分应该去抱这一个趋势。其中Reactjs相信是支付webapp的超人,那段时日用相会经改建官方实例alt-tutorial来修Reactjs相关的学问。

上一篇《稍白学react之页面BaseLayout框架及微信的坑》我们念了哪些为顺序Components提供一个基础之翁框架组件来处理不同页面的Title的展现和Style样式的显得。

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.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页面模版文件之变更。

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"
  },

这就是说我们怎么才可以是的拿支付配置与生产安排分离开来呢?