5

在事件项目中,一个页面常常有很多资源要加载,举出一个实战中的例子要求如下:

  1. 项目采用ES6语言加react框架;
  2. 给页面假如google analytics, 这部分代码需要内嵌进head标签里去。
  3. 给页面假如Disqus用户评论, 这部分代码需要异步加载以提升首屏加载速度。
  4. 压缩和分类JavaScript和css代码,提升加载速度。

以下是发布到线上的代码 :

<html>
<head>
  <meta charset="UTF-8">
  <!--注入 Chunk app 依赖的 CSS-->
  <style rel="stylesheet">h1{color:red}</style>
  <!--内嵌 google_analytics 中的 JavaScript 代码-->
  <script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-XXXXX-Y', 'auto');
ga('send', 'pageview');
  </script>
  <!--异步加载 Disqus 评论-->
  <script async="" src="https://dive-into-webpack.disqus.com/embed.js"></script>
</head>
<body>
<div id="app"></div>
<!--导入 app 依赖的 JS-->
<script src="app_746f32b2.js"></script>
<!--Disqus 评论容器-->
<div id="disqus_thread"></div>
</body>
</html>

构建出的目录结构为:

dist
├── app_792b446e.js
└── index.html

可以看到部分代码被内嵌进入了HTML的head标签中,部分文件的文件名称被打上根据文件内容算出的Hash值,并且加载这些文件的URL地址也被正常的注入到了HTML中。如果还是手写HTML文件去完成以上要求,这就会使工作变得复杂、易错、项目难以维护。

解决方案

推荐一个用于方便的解决以上为的webpack插件web-webpack-plugin
首先,修改webpack配置:

const path = require('path');
const UglifyJsPlugin = require('webpack/lib/optimize/UglifyJsPlugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const DefinePlugin = require('webpack/lib/DefinePlugin');
const { WebPlugin } = require('web-webpack-plugin');

module.exports = {
    entry: {
        app: './main.js' //app的js入口文件
    },
    output: {
        filename: '[name]_[chunkhash:8].js'给输出的文件加上hash值
        path: path.resolve(__dirname, './dist')
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                use: ['babel-loader'],
                //排除node_modules目录下的文件
                //该目录下的文件都是ES5语法,没必要再通过babel去转换
                exclude: path.resolve(__dirname, "node_modules")
            },
            {
                test: /\.css/, //增加对css文件的支持
                //提取出chunk中的css代码到单独的文件中
                use: ExtractTextPlugin.extract({
                    use: ["css-loader?minimize"] //压缩css代码
                })
            }
        ]
    },
    plugins: [
        //使用本文的主角WebPlugin,一个WebPlugin对应一个HTML文件
        new WebPlugin({
            template: "./template.html", //HTML模板文件所在的文件路径
            filename: "index.html" //输出HTML的文件名称
        }),
        new ExtractTextPlugin({
            filename: `[name]_[contenthash:8].css`,//给输出的css文件名称加上hash值
        }),
        new DefinePlugin({
            //定义NODE_ENV环境变量为production,以去除源码中只有开发时才需要的部分
            "process.env": {
                NODE_ENV: JSON.stringify("production")
            }
        }),
        //压缩输出的JavaScript代码
        new UglifyJsPlugin({
            // 最紧凑的输出
            beautify: false,
            // 删除所有的注释
            comments: false,
            compress: {
                // 在UglifyJs删除没有用到的代码时不输出警告
                warnings: false,
                // 删除所有的 `console` 语句,可以兼容ie浏览器
                drop_console: true,
                // 内嵌定义了但是只用到一次的变量
                collapse_vars: true,
                // 提取出出现多次但是没有定义成变量去引用的静态值
                reduce_vars: true,
              }
        })
    ]
}

以上配置中,大多数都是按照前面已经讲过的内容增加的配置如

  1. 增加对css文件的支持, 提取出chunk中的css代码到单独的文件中,压缩css代码;
  2. 定义NODE_ENV环境变量为production,以去除源码中只有开发时才需要的部分;
  3. 给输出的文件名称加上hash值;
  4. 压缩输出的JavaScript带啊。

fsrookie
2.9k 声望256 粉丝

目前很多文章都是摘抄记录其他教程。见谅。