webpack使用说明

1 webpack使用说明

webpack是目前流行的前端模块化打包工具,通过丰富的插件和扩展功能,可以高效的实现前端构建,简化工作量。webpack的核心部分实现了js的模块化方案,每一个js文件作为一个模块,在构建阶段进行打包。而webpack的 加载器(loader)插件(plugins) 提供了更多的功能,使webpack可以处理几乎所有的前端资源,如css文件,html文件以及图片等静态资源。

本文档基于webpack2.x版本编写,webpack2x和webpac1x有比较明显的改变。按照此文档说明操作前请确认正在使用的是webpack2.x版本。

2 webpack安装以及环境搭建

2.1 node环境

webpack依赖于nodejs环境,因此在使用webpack前确保已经安装了nodejs。

2.2 安装webpack

在命令行中使用npm安装webpack,采用全局模式:

npm install webpack -g  

2.3 运行方式

有3种常用的运行webpack打包的方式。首先打开node命令行工具,进入到项目目录下:

2.3.1 使用默认配置文件

默认情况下webpack会在项目目录下寻找webpack.config.js文件作为配置文件。在命令行中输入:

webpack

此时webpack使用webpack.config.js文件作为配置文件运行。

2.3.2 指定配置文件

webpack允许使用自定义的配置文件。为了区分开发环境和生产环境,我们可以分别创建两个配置文件webpack.config.dev.js(开发)和webpack.config.pro.js(生产).

使用开发环境的配置文件webpack.config.dev.js

webpack --config webpack.config.dev.js

使用生产环境的配置文件webpack.config.pro.js

webpack --config webpack.config.pro.js

2.3.3 npm scripts

当命令行中需要输入的指令较多时,比如:

webpack --config widget/webpack.config.pro.js process.env.NODE_ENV="'production'" 

为了简化输入过程,以及避免输入错误,我们可以利用npm scripts命令执行构建。
首先在项目目录下创建package.json文件:

npm init

在文件中找到”scripts”字段,并设置构建命令:

{
  // ...
  "scripts": {
    "build": "webpack --config widget/webpack.config.pro.js process.env.NODE_ENV="'production'""
  },
  // ...
}

在命令行中运行:

npm run build

以上两种方法的效果完全一致。

2.4 配置文件简单示例

webpack.config.js文件:

var path = require('path');

module.exports = {
    // 入口文件
    entry: './app/index.js',
    // 输出文件
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist')
    },
    // 模块文件的处理声明
    module: {
        // ...
    },
    // 模块文件别名
    resolve: {
        // ...
    },
    // 插件
    plugins: [
        // ...
    ]
};

3 webpack在F1平台的使用

平台webpack结构图:


这里写图片描述

3.1 区分生产环境和开发环境

webpack可以设置不同的配置文件,只需在运行webpack时通过参数给出配置文件:

webpack --config 配置文件路径及文件名

单独建立开发环境和生产环境的配置文件,可以提高开发效率和质量。在两种模式中,存在下列不同的需求:

——开发环境生产环境
自动编译及刷新
source-map
代码混淆
文件版本号

开发环境的侧重点是提升调试的效率,生产环境的侧重点是提升代码在浏览器运行的性能。

目前,F1平台的前端UI组件库使用webpack进行打包。组件库资源在public_libraries 和 widget_libraries中。其中public_libraries文件夹中是平台组件依赖的第三方库文件,widget_libraries文件夹中是组件库的源码及静态资源。项目目录如下:

public_libraries


这里写图片描述

目录名内容
vendor平台依赖的第三方库文件
dist打包后输出的文件
webpack-configwebpack各配置项的设置

widget_libraries


这里写图片描述

目录名内容
src平台组件js源码
stylus平台样式文件源码
dist打包后输出目录
webpack-configwebpack各配置项的设置

webpack打包平台组件库时,我们要处理的资源文件按类型分为:


这里写图片描述

打包过程分为两步:

  1. 打包第三方库文件
  2. 打包平台组件代码

下面详细说明不同类型文件的处理方式。

3.2 第三方库文件

第三方库文件的特点是不属于平台源码,且修改频率较低。因此理想情况是三方代码和组件代码独立打包,当组件代码修改时,只需要重新打包组件代码而不需打包三方代码。这样可以提高打包的效率,同时在浏览器端可以充分利用缓存机制减少页面请求资源的时间。基于以上的考虑,我们选择webpack提供的dll方案处理三方文件(另一种官方提供的方案是CommonsChunkPlugin)。

dll方案的思路是webpack对三方库文件单独做一次打包,生成dll.bundle.js文件和dll-manifest.json文件,该文件是组件库依赖的文件。之后打包组件库文件时需要声明依赖的dll文件。实现dll方案需要两个插件,DllPlugin和DllReferencePlugin。

现在我们把lib下的文件从原目录中提取出来,并建立一个新的文件夹public_libraries,如下图:


这里写图片描述

vendor和原来的lib内容相同,包含所有第三方库文件。webpack-config是webpack的配置文件,dist是打包生成的文件。

3.2.1 DllPlugin配置

webpack.vendor.config.js

三方库文件配置:

module.exports = {
    //...
    output: {
        //...
        library: '[name]_lib' // 输出文件声明为库文件
    }, 
    plugins: [
        // DllPlugin插件
        new webpack.DllPlugin({
            context: '',  
            path: path.resolve(dirVars.dllDir, './dll-manifest.json'),  // 输出manifest文件的绝对路径
            name: 'dll_lib',  // 库文件的名字,和output.library一致
        })
    ]
}

使用dll插件后,webpack打包后会生成一个manifest.json文件,该文件是库文件dll.bundle.js的map:


这里写图片描述

webpack.widget.config.js

组件库配置:

module.exports = {
    //...
    plugins: [
        // DllReferencePlugin插件
        new webpack.DllReferencePlugin({
            context: path.resolve(dirVars.staticRootDir, '../'),
            manifest: path.resolve(dirVars.dllDir, './dll-manifest.json'),// manifest文件路径
            name: 'dll_lib'    
        })
    ]
}

3.2.2 全局变量声明

webpack打包时会把js文件的作用域限定在本文件以内,即文件中的全局变量在其他文件中无效。但是对于第三方库如jquery、moment等,我们有时需要以全局变量的形式使用(兼容过去的代码或是在没有模块化的环境中)。想要在webpack生成的文件中暴露出库文件的全局变量,我们需要利用’expose-loader’。

‘expose-loader’用于把某个模块的作用域提升至全局。首先通过npm安装:

npm i expose-loader --save

在配置文件的module中使用’expose-loader’声明全局模块:

module: {
    rules: [
        {
            test: require.resolve(dirVars.vendorDir + '/jquery/jquery-1.10.2.js'),// test指定模块路径
            use: ['expose-loader?$', 'expose-loader?jQuery']// 全局变量名字是$和jQuery  
        },
        {
            test: require.resolve(dirVars.vendorDir + '/moment/moment.js'),
            use: ['expose-loader?moment']
        }
    ] 
}

全局变量现在还是无效的,我们还需要在其他文件中通过require()的方式引用jquery和moment,这样全局变量才会生效。在vendor目录下的init.vendor.js文件的作用就是引用所有声明为全局模块的第三方库文件。在组件使用webpack打包时会使用这个文件。

3.2.3 模块间通用变量

根据js模块化规范,一个模块想要引用另一个模块必须显示的引用,比如require或import。但是对于jquery这样的基础库,每次都require() 显然会降低效率。通过 ProvidePlugin可以很好的解决这个问题。在此之前,我们先设置配置文件中的resolve.alias属性:

module.exports = {
    resolve: {
        alias: {
            // 设置jquery-1.10.2.js模块的别名为jquery
            jquery: path.resolve(dirVars.vendorDir + '/jquery/jquery-1.10.2.js') 
        }
    }
}

设置别名后,我们可以这样引用jquery模块:

    require('jquery');

只需要在require中写’jquery’,而不用写完整的路径。但是还不够方便,我们希望不用require,当模块中有$或jQuery时,自动引用jquery模块。这时就需要使用ProvidePlugin插件:

plugins: [
    new webpack.ProvidePlugin({
        $: 'jquery',
        jQuery: 'jquery'
    })
]

$('#item'); 
jQuery('#item'); 

此时会自动引用jquery模块。

3.2.4 第三方库文件打包总结

打包后,我们在dist目录下得到dll.bundle.js和dll-manifest.json两个文件。使用三方库文件需要在html页面中引用dll.bundle.js文件,同时还要引用组件库文件打包的结果(后面会有详细说明)。dll-manifest.json文件作为引用关系说明在组件库打包时使用。


这里写图片描述

3.3 平台js源码

平台依赖的三方库文件单打包,而js源码、stylus文件和其他静态资源一起打包。分离三方库文件后平台组件库的项目目录如下:


这里写图片描述

3.3.1 dll库依赖

首先,我们应该在配置文件中声明对三方库dll文件的依赖,需要使用DllReferencePlugin:

plugins: [
    // DllReferencePlugin中的属性值应该和三方库打包的DllPlugin中的属性值对应
    new webpack.DllReferencePlugin({
        context: path.resolve(dirVars.staticRootDir, '../'),
        manifest: path.resolve(dirVars.dllDir, './dll-manifest.json'),// manifest文件路径
        name: 'dll_lib'
    })
]

3.3.2 全局变量和模块间通用变量声明

在平台的组件代码以及业务代码中,有一些全局变量被广泛使用,比如F1Map,F1DataTable,DateFormat。为了兼容原有代码,我们需要把这些变量设置为模块间通用的变量和全局变量。声明方式和三方库文件一致,使用ProvidePlugin和expose-loader。

设置模块别名:

resolve: {
    alias: {
        F1Map: path.resolve(dirVars.srcDir + '/util/jquery.f1.map.js'),
    }    
}

声明模块间通用变量:

plugins: [
    new wepack.ProvidePlugin({
        F1Map: 'F1Map',
    })
]

声明全局变量:

module: {
    rules: [
        {
            test: path.resolve(dirVars.srcDir + '/util/jquery.f1.map.js'),
            use: ['expose-loader?F1Map']
        }
    ]
}

3.4 stylus文件处理

平台组件的样式文件源码使用stylus编写。打包后的样式文件应该实现以下需求:
1. stylus文件编译为css文件。
2. css代码与js代码分离,生成单独的css样式文件。
3. 样式文件的输出路径可以指定。
4. 输出文件的路径改变后,样式文件中引用的静态资源路径自动变化,比如背景图片和字体图标。

3.4.1 样式文件编译

webpack默认把所有引用的资源作为js文件处理,所以对于stylus、css文件我们需要通过加载器(loader)处理。在这里使用’stylus-loader’,’css-loader’,’style-loader’。配置项设置如下:

module: {
    rules: [
        {
            test: /\.styl$/,
            use: [
                {loader: 'style-loader'},
                {loader: 'css-loader'},
                {loader: 'stylus-loader'}
            ]
        }
    ]
}    

编译后得到的css代码与js代码在同一个文件里,以

3.4.2 css代码分离

为了分离css代码,我们引入’extract-text-webpack-plugin’插件。它能帮助我们生成单独的css样式文件。

var extractTextPlugin = require('extract-text-webpack-plugin');

// 创建提取器实例,参数是输出文件的路径及文件名,用于处理平台蓝色主题的样式文件
var extractStylusBlue = new extractTextPlugin('css/blue/[name].bundle.css'); 

module.exports = {
    ...
    module: {
        rules: [
            {
                test: /\.styl$/,  // 正则,匹配文件模块
                include: [
                    path.resolve(dirVars.stylusDir, 'blue')  // 限定目录,缩小匹配范围
                ],
                // 使用文件提取器处理stylus文件
                use: extractStylusBlue.extract({
                    use: [{
                        loader: 'css-loader',
                        options: {
                            sourceMap: true
                        }
                    }, {
                        loader: 'stylus-loader'
                    }],
                    // 设置输出文件基础路径,默认和js文件输出在同一个目录
                    publicPath: '../../'
                })
            }
        ]
    },
    plugins: [
        extractStylusBlue  // 注意在插件中加入提取器,否则不起作用
    ]
}

利用loader和’extract-text-webpack-plugin’插件可以成功编译打包平台组件库中的样式文件。生成文件如下图所示:


这里写图片描述

3.5 其他静态资源

目前为止看,我们已经解决了第三库文件、js源码和stylus样式文件的编译打包问题,还剩下的就是处理项目中的其他静态资源。和stylus文件一样,我们需要增加新的加载器(loader),这里要用到’file-loader’,’url-loader’。

3.5.1 图片

图片使用’url-loader’:

    module: {
        rules: [
            {
                test: /\.(png|jpg|gif)$/,  // 匹配图片扩展名
                use: {
                    loader: 'url-loader',  // 加载器声明 
                    options: {
                        limit: 8192,  // 小于8192kb的图片以base64编码的形式转换为元数据,不生成独立的图片文件  
                        name: 'image/[name].[ext]'  //name中加入路径用于解决样式文件中url路径错误的问题
                    }
                }
            }
        ]
    }

3.5.2 字体图标

字体图标使用’file-loader’:

    module: {
        rules: [
            {
                test: /\.(eot|svg|ttf|woff)$/,  // 匹配图片扩展名
                use: {
                    loader: 'file-loader',  // 加载器声明 
                    options: {
                        name: 'fonts/[name].[ext]'  //name中加入路径用于解决样式文件中url路径错误的问题
                    }
                }
            }
        ]
    }

打包后生成文件如下:


这里写图片描述

3.6 组件库使用

至此平台所用的全部资源文件都可以通过webpack进行处理,并在dist目录中输出。组件库打包后,输出目录dist内容如下:


这里写图片描述

css是平台的样式文件,fonts是字体图标,images是图片,scripts是js文件。如果我们想要在页面中使用平台组件库,只需在页面中引用这些文件就可以了,就像以前引用jquery文件一样。注意不要忘记引用平台依赖的三方库。下图是引用示例:

<!-- 组件库样式文件 -->
<link rel="stylesheet" type="text/css" href="/jquery/css/blue/widget.bundle.css">
<!-- 平台组件依赖的三方库 -->
<script type="text/javascript" src="/public/dll.bundle.js"></script>
<!-- 平台组件库文件 -->
<script type="text/javascript" src="/jquery/scripts/widget.bundle.js"></script>
<!-- 当前页面业务代码 -->
<script type="text/javascript" src="/sysconfig/scripts/syscode.js"></script>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值