webpack 多页面|入口支持和公共组件单独打包--转载
转载自:http://www.jb51.net/article/117490.htm
本篇主要介绍:如何自动构建入口文件,并生成对应的output;公共js库如何单独打包。
多入口文件,自动扫描入口。同时支持SPA和多页面型的项目
公共js库如何单独打包。
基础结构和准备工作
以下示例基于上一篇进行改进,上一篇项目源码
目录结构说明
| 1 2 3 4 5 6 7 8 9 10 11 12 13 | .├── package.json    # 项目配置├── src      # 源码目录│ ├── pageA.html    # 入口文件a│ ├── pageB.html    # 入口文件b│ ├── css/     # css资源│ ├── img/     # 图片资源│ ├── js     # js&jsx资源│ │ ├── pageA.js    # a页面入口│ │ ├── pageB.js    # b页面入口│ │ ├── lib/    # 没有存放在npm的第三方库或者下载存放到本地的基础库,如jQuery、Zepto、avalon│ ├── pathmap.json   # 手动配置某些模块的路径,可以加快webpack的编译速度├── webpack.config.js   # webpack配置入口 | 
一:自动构建入口
官方多入口示例
webpack默认支持多入口,官方也有多入口的示例。配件文件webpack.config.js如下
| 1 2 3 4 5 6 7 8 9 10 11 12 13 | //已简化varpath = require("path");module.exports = { entry: {  pageA: "./pageA",  pageB: "./pageB" }, output: {  path: path.join(__dirname, "js"),  filename: "[name].bundle.js",  chunkFilename: "[id].chunk.js" }} | 
每新增一个页面就需要在webpack.config.js的entry 中增加一个 pageC:"./pageC",页面少还好,页面一多,就有点麻烦了,而且配置文件,尽可能不改动。那么如何支持不修改配置呢?
自动构建入口函数
entry实际上是一个map对象,结构如下{filename:filepath},那么我们可以根据文件名匹配,很容易构造自动扫描器:
npm 中有一个用于文件名匹配的 glob模块,通过glob很容易遍历出src/js目录下的所有js文件:
安装glob模块
| 1 | $ npm installglob --save-dev | 
修改webpack.config.js 配置,新增entries函数,修改entry:entries(),修改output的filename为"[name].js"
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | //引入globvarglob = require('glob')//entries函数varentries= function() { varjsDir = path.resolve(srcDir, 'js') varentryFiles = glob.sync(jsDir + '/*.{js,jsx}') varmap = {}; for(vari = 0; i < entryFiles.length; i++) {  varfilePath = entryFiles[i];  varfilename = filePath.substring(filePath.lastIndexOf('\/') + 1, filePath.lastIndexOf('.'));  map[filename] = filePath; } returnmap;}//修改入口,已经修改outp的filenamemodule.exports = { //entry: "./src/js/index.js", entry: entries(), output: {  path: path.join(__dirname, "dist"),  filename: "[name].js" }, ...... //以下省略,可以见下文详细配置 | 
测试
1.在src/js目录中新增pageA.js
| 1 2 3 | //js只有两行代码,在body中加一句话var$ = require("jquery")$("<div>这是jquery生成的多页面示例</div>").appendTo("body") | 
2.新增pageA.html,也顺便修改原来的index.html 对于js文件名的更改
| 1 2 3 4 5 6 7 8 9 10 | <!DOCTYPE html><htmllang="en"><head><metacharset="UTF-8"><title></title></head><body><scriptsrc="../dist/index.js"></script></body></html> | 
3.执行webpack,启动dev-server
| 1 2 | $ webpack$ webpack-dev-server | 

OK,成功打包生成pageA.js,成功运行
二:公共库单独打包
先来分析下,上个步骤打包的日志:

index.js 依赖了avalon 和 jquery,然后打包后的index.js 有480kb
pageA.js 只用了jquery,然后打包后的js 有294kb
那么如果引用的lib库多一点,又被很多页面引用,那么lib库就会被重复打包到page.js中去,模块越多重复加载的情况越严重。
如果把公共代码提取出来作为单独的js,那么就到处可以复用,浏览器也就可以进行缓存,这时候就需要用到webpack内置插件WebPack.optimize.CommonsChunkPlugin
CommonsChunkPlugin 介绍
使用
| 1 | newwebpack.optimize.CommonsChunkPlugin(options) | 
Options
翻译得比较简单,详见官方说明:
- options.name or options.names(string|string[]): 公共模块的名称
- options.filename (string): 公开模块的文件名(生成的文件名)
- options.minChunks (number|Infinity|function(module,count) - boolean): 为number表示需要被多少个entries依赖才会被打包到公共代码库;为Infinity 仅仅创建公共组件块,不会把任何modules打包进去。并且提供function,以便于自定义逻辑。
- options.chunks(string[]):只对该chunks中的代码进行提取。
- options.children(boolean):如果为true,那么公共组件的所有子依赖都将被选择进来
- options.async(boolean|string):如果为true,将创建一个 option.name的子chunks(options.chunks的同级chunks) 异步common chunk
- options.minSize(number):所有公共module的size 要大于number,才会创建common chunk
2个常用的例子,更多例子见官方说明:
1.Commons chunk for entries:针对入口文件提取公共代码
| 1 2 3 4 5 6 7 8 9 10 11 12 13 | newCommonsChunkPlugin({ name: "commons", // (the commons chunk name) filename: "commons.js", // (the filename of the commons chunk) // minChunks: 3, // (Modules must be shared between 3 entries) // chunks: ["pageA", "pageB"], // (Only use these entries)}) | 
2.Explicit vendor chunk:直接指定第三方依赖库,打包成公共组件
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | entry: { vendor: ["jquery", "other-lib"], app: "./entry"}newCommonsChunkPlugin({ name: "vendor", // filename: "vendor.js" // (Give the chunk a different name) minChunks: Infinity, // (with more entries, this ensures that no other module // goes into the vendor chunk)}) | 
CommonsChunkPlugin使用
基于上篇的项目,参考上面的第二个例子,我们将jquery 和 avalon 提取出来打包成vendor.js
完整的webpack.config.js 如下:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | ```js varwebpack = require("webpack"); varpath = require("path"); varsrcDir = path.resolve(process.cwd(), 'src'); varnodeModPath = path.resolve(__dirname, './node_modules'); varpathMap = require('./src/pathmap.json'); varglob = require('glob') varCommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin; varentries= function() { varjsDir = path.resolve(srcDir, 'js') varentryFiles = glob.sync(jsDir + '/*.{js,jsx}') varmap = {}; for(vari = 0; i < entryFiles.length; i++) {  varfilePath = entryFiles[i];  varfilename = filePath.substring(filePath.lastIndexOf('\/') + 1, filePath.lastIndexOf('.'));  map[filename] = filePath; } returnmap;}module.exports = { //entry: "./src/js/index.js", //entry: entries(), entry: Object.assign(entries(), {  // 用到什么公共lib(例如jquery.js),就把它加进vendor去,目的是将公用库单独提取打包  'vendor': ['jquery', 'avalon'] }), output: {  path: path.join(__dirname, "dist"),  filename: "[name].js" }, module: {  loaders: [   {test: /\.css$/, loader: 'style-loader!css-loader'}  ] }, resolve: {  extensions: ['.js', "", ".css"],  root: [srcDir,nodeModPath],  alias: pathMap,  publicPath: '/' }, plugins: [  newCommonsChunkPlugin({   name: 'vendor',   minChunks: Infinity  }) ]}``` | 
测试、验证
1.修改入口(Object.assign 是html5.js里面的....)
| 1 2 3 4 5 | //entry: entries(),entry: Object.assign(entries(), { // 用到什么公共lib(例如jquery.js),就把它加进vendor去,目的是将公用库单独提取打包 'vendor': ['jquery', 'avalon']}), | 
2.加入插件CommonsChunkPlugin
| 1 2 3 4 5 6 7 8 | varCommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin;config 中增加 plugins plugins: [  newCommonsChunkPlugin({   name: 'vendor',   minChunks: Infinity  }) ] | 
3.修改index.html 和 pageA.html,增加对verdor.js的引用
| 1 2 3 | <scriptsrc="../dist/vendor.js"></script><scriptsrc="../dist/index.js"></script>//<scriptsrc="../dist/pageA.js"></script> | 
4.执行webpack
$ webpack

结果分析
可以看到index.js 就只有457 bytes了,pageA.js 227bytes。vendor.js 是集成了jquery+avalon,所以有488kb。
这样vendor.js 就可以重复利用了,也方便浏览器进行缓存。
调试过程中发现
Uncaught ReferenceError: webpackJsonp is not defined
这个是因为当时把vendor.js引入 放到了page.js 后面,导致page.js执行异常,所以,请一定把vendor.js 放在前面。
生成后的index.js就很轻便了,第三方库都被打包到vendor中了,代码如下:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | webpackJsonp([0],[/* 0 *//***/function(module, exports, __webpack_require__) { /**  * Created by sloong on 2016/6/1.  */ //avalon 测试 varavalon = __webpack_require__(1); avalon.define({  $id: "avalonCtrl",  name: "Hello Avalon!" }); /* //zepto 测试 require("zepto") $("<div>这是zepto生成的</div>").appendTo("body")*/ //jquery 测试 var$ = __webpack_require__(2) $("<div>这是jquery生成的</div>").appendTo("body")/***/}]); | 
页面测试均正常

OK,本篇结束了。如何让webpack 自动在html文件中引入所需js的script标签,如何给js和css文件加了hash值,这样浏览器每次都能检测到文件变更,而且也不需要手动修改引入的js文件链接,这些操作webpack都能轻松搞定。
webpack 多页面|入口支持和公共组件单独打包--转载的更多相关文章
- webpack 多页面支持 & 公共组件单独打包
		webpack - 多页面/入口支持 & 公共组件单独打包 webpack系列目录 webpack 系列 一:模块系统的演进 webpack 系列 二:webpack 介绍&安装 we ... 
- NuGet多个项目依赖的公共组件如何打包
		会有这样一种情况:在同一个解决方案下面,类库A是独立的,类库B是依赖于类库A的:类似这样: 所以在使用类库B时必须引入类库A的东西,这时如果作为nuget包打包发布,有如下的解决思路: 1.在整个解决 ... 
- 公共组件及脚手架webpack模板
		一.公共组件的创建和使用 前面已经学习vue组件时,了解了公共组件,但在脚手架项目中只使用过局部组件.这里是讲解全局组件如何在脚手架项目中去使用. 1.创建全局组件 在src/components/C ... 
- 基于webpack实现多html页面开发框架六  提取公共代码
		一.解决什么问题 1.如果a.js和b.js都引用了common.js,那在打包的时候common.js会被重复打入到a.js和b.js,造成重复打包 2.单独打包common.js对性能有帮助,浏览 ... 
- webpack+vue多入口环境搭建
		项目地址:https://pan.baidu.com/s/1c1Dflp2 使用前提:安装nodejs环境,webpack的配置官网的例子跟着跑一遍,会vue开发 研究webpack+vue研究了一个 ... 
- webpack 单页面应用实战
		这篇文章将介绍如何利用 webpack 进行单页面应用的开发,算是我在实际开发中的一些心得和体会,在这里给大家做一个分享.webpack 的介绍这里就不多说了,可以直接去官网查看. 关于这个单页面应用 ... 
- [转] vue&webpack多页面配置
		前言 最近由于项目需求,选择使用vue框架,webpack打包直接使用的vue-cli,因为需要多页面而vue-cli只有单页面,所以就决定修改vue-cli的配置文件来满足开发需求. html-we ... 
- webpack创建页面的过程
		1.项目文件夹中创建各类型文件放置的文件夹,如:iTestingWeb文件夹下创建src dist文件夹,用途:src为源码 dist为生成后的文件放置位置,然后在源码文件夹中进一步按文件类型增加文件 ... 
- react初探(二)之父子组件通信、封装公共组件
		一.前言 在组件方面react和Vue一样的,核心思想玩的就是组件,下面举两个组件常用的情景. 场景一:假如我们现在有一个页面包含表格以及多个弹框,这种时候如果将这个页面的业务代码写在一个组件中,那么 ... 
随机推荐
- 20162314 Experiment 2 - Tree
			Experiment report of Besti course:<Program Design & Data Structures> Class: 1623 Student N ... 
- 安卓端通过http对Mysql进行增删改查
			各类it学习视频,大家都可以看看哦!我自己本人都是通过这些来学习it只知识的! 下面是视频链接转自:http://www.cnblogs.com/yzxk/p/4749440.html Android ... 
- 第二篇——VC++简单随机四则运算
			目标:编写最简单的四则运算,类似A+B=C: 想法:建立一个Win32控制台应用程序,A和B用随机数表示,运算符号用0~3的数字对应,然后计算并输出即可: 具体过程: 利用函数rand(),返回一个0 ... 
- Leetcode题库——3.无重复字符的最长子串
			@author: ZZQ @software: PyCharm @file: lengthOfLongestSubstring.py @time: 2018/9/18 20:35 要求:给定一个字符串 ... 
- 【Coursera】主成分分析
			一.问题 主方向的概念是什么?为什么降低维度的方法是使方差最大化? 假设某两个特征之间成线性关系,在二维平面上的表示就是数据点呈线性分布,那么可以通过将数据在主方向上进行投影,得到一个一维的数据,这个 ... 
- week4d:个人博客作业
			7,程序结果的显示 1,界面 2,选第一选项. 3,输入3个数后. 4,选择第一个. 5,输入第4个数字. 6,再次进行一轮游戏. 7,选择是否要看历史记录. 8,进入下一轮游戏. 9,开始第二轮数字 ... 
- WPF里面制作圆角文本框
			转自:http://www.cnblogs.com/mengxin523/archive/2010/04/04/1704448.html 本以为WPF里面的XAML会很强大,可以设置很多属性,比如文本 ... 
- Internet History, Technology and Security (Week 6)
			Week 6 Technology: Transport Control Protocol (TCP) Welcome to Week 6 of IHTS. We are in our second ... 
- Beta阶段——第二篇 Scrum 冲刺博客
			i. 提供当天站立式会议照片一张: ii. 每个人的工作 (有work item 的ID) (1) 昨天已完成的工作: 账单收支分明,剩余舍费关联成功 (2) 今天计划完成的工作: 账单删除功能,排序 ... 
- 简单 dp
			1.摆花问题 题目描述小明的花店新开张,为了吸引顾客,他想在花店的门口摆上一排花,共m盆.通过调查顾客的喜好,小明列出了顾客最喜欢的n种花,从1到n标号.为了在门口展出更多种花,规定第i种花不能超过a ... 
