7. 源码

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

同时

正文由世界会桂林分舵编写,转载需授权,喜欢点个赞,吐槽请评论,进一步交换请关注我领域会威海分舵以及《微信小程序支付》主题。

《未完待续》

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

首要需要解决的题材如下:

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

那么大家怎么才能科学的将开发配置和生育布局分离开来啊?

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;

区分别当前需要打包的是开发条件仍旧生育环境之后,大家下一步要做的就是将它们的布局代码分开。

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>

前日自己会尝试就自己踩到的一个坑起先,通过对webpack做越来越的修改,来学习更高级点的webpack相关的知识点。

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>

世界会宜昌分舵注:随着微信应用号的呼之欲出,相信新一轮的APP变革即将发生。作为行业内人员,我们很应该去拥抱这多少个方向。其中Reactjs相信是开发webapp的探花,这段时光将会因此改造官方实例alt-tutorial来学学Reactjs相关的知识。

react-webpack.png

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页面模版文件的变通。

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

3. 别离开发和生产安排

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

  • FOUC问题
  • 生产和支出配置分离
  • 自动生成index.html页面模版文件
  • 哈希文件名
  • 清理垃圾堆构建文件

相关文章

网站地图xml地图