本需要对webpack已有一定的了解,如果你没接触过webpack或者刚刚接触webpack,可以考虑先看一下我的这篇教程。





##1.打包多文件
之前,当需要打包多个而文件时,我是这么写的:
```javascript
module.exports={
entry:{
"page/main/main":'./src/js/index.js',
"page/car/car":"./src/js/car.js",
"page/goods/goods":"./src/js/goods.js",
},
output:{
filename:"[name].[hash].js",
path:path.resolve(__dirname,'dist')
},
plugins:[
new webpack.HotModuleReplacementPlugin(),
new htmlWebpackPlugin({
title:"首页",
template:'./src/index.html',
filename:"index.html",
chunks:["page/main/main"]
}),
new htmlWebpackPlugin({
title:"购物车",
template:'./src/index.html',
filename:"car.html",
chunks:["page/car/car"]
}),
new htmlWebpackPlugin({
title:"商品",
template:'./src/index.html',
filename:"goods.html",
chunks:["page/goods/goods"]
})
]
```

可以发现,我们在entry中手动引入了多个文件; 在plugins中,我们又手动的多次new htmlWebpackPlugin()。

虽然能够正常的运行,然而存在很多限制。

  • 首先:存在大量重复的代码。现在只有3个页面,假如现有10个页面,那么你就得手动的new10次,在enrty中输入10个入口。

  • 其次:当增加新的页面时,又得过来webpack的配置里面手动的再加入到入口文件中。

明显的,对于这些重复的而且长得很像的,如果能自动获取到需要配置的文件,并且在一个循环里面调用,那就方便多了。

使用node.js的golb模块来获取文件

//引入glob
var glob= require('glob'); //同步读取src目录下所有的html文件
var files = glob.sync('./src/*.html');
var entry={};
var plugins=[]; //循环将文件
files.forEach(function(item,i){
//item类似:./src/index.html var htmlName=item.slice(item.lastIndexOf("/")+1);
//最后生成的文件名只需要最后面的名字index.html var name=htmlName.split(".")[0]; //添加到entry入口,并制定生成文件的目录
entry["page/"+name+"/"+name]='./src/js/'+name+'.js' //生成htmlWebpackPlugin实例
plugins.push(
new htmlWebpackPlugin({
template:item,
filename:htmlName,
chunks:["page/"+name+"/"+name]
})
)
}); module.exports={
entry:entry,
output:{
filename:"[name].[chunkhash].js",
path:path.resolve(__dirname,'dist'),
}, module:{
rules:[
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
},
]
},
plugins:plugins
}

可以发现,使用glob.sync来读取文件并进行循环操作,原本需要手动操作的部分,循环已经帮我们处理好了。原本需要很多new new htmlWebpackPlugin()已经不再存在,而且即使后续需要添加新的页面,也不需要我们手动去添加,glob.sync会自己去读取所有的*.html文件,接着循环会帮我们处理。

这里需要注意的地方就是,index.html对应的js文件必须为index.js,ceshi.html文件对应的文件必须为ceshi.js。至于js里面需要引入其他库,或者自己写的工具函数,哪个页面需要,只需引入即可,webpack会自己处理好。

2.使用DLL提取公共库



当页面存在引用相同的库时,最好还是将这些库文件提取到单独的文件,页面只保留业务逻辑的js代码。

为了提取文件,有2中处理方案:
  • 使用CommonsChunkPlugin来提取

在上面的代码上增加:(以下这部分代码只在使用CommonsChunkPlugin时需要)

  entry.vendor=[
//举例如下:
"vue","vuex","axios","jquery","vue-router","moment","lodash"
]; plugins=[
new webpack.optimize.CommonsChunkPlugin({
name:["vendor","manifest"]
})
] //修改循环中的chunks, 增加vendor以及manifest:
files.forEach(function(item,i){
plugins.push(
new htmlWebpackPlugin({
template:item,
filename:htmlName,
chunks:["page/"+name+"/"+name,"vendor","mainfest"]
})
)
});

再执行webpack,可以发现公共的库已经被提取到单独的vendor文件。

  • 使用DLL

对于 CommonsChunkPlugin,webpack 每次打包实际还是需要去处理这些第三方库,只是打包完之后,能把第三方库和我们自己的代码分开。

DLLPlugin 则是能把第三方代码完全分离开,即每次只打包项目自身的代码。

这里我使用的是autodll-webpack-plugin。

//安装模块
npm install --save-dev autodll-webpack-plugin //引入模块
var AutoDllPlugin = require('autodll-webpack-plugin'); 在plugins中添加插件:(需要放在循环之前,防止数组被重新赋值)
var plugins=[
new AutoDllPlugin({
//文件名
filename: '[name].[hash].js', //打包后的文件路径
path: './page/common/', //是否将生成的Js文件注入到html文件中
inject:true, //需要分离的库
entry: {
vendor: [
"vue","vuex","axios","jquery","vue-router","moment","lodash","vue-touch","vue-lazyload"
]
}, //压缩代码(注意这里是压缩分离出来的库文件代码,跟外面的要区分开来,如果外面的需要压缩,外面的plugins中也需要new一个压缩实例)
plugins: [
new webpack.optimize.UglifyJsPlugin()
]
})
]

执行webpack命令,可以发现公共的库文件也被打包到单独的文件了。

autodll-webpack-plugin在内存中缓存了文件,所以当你第二此执行webpack命令进行打包时,可以明显发现打包时间少了很多。

CommonsChunkPlugin每次都全部重新打包再进行分离,所以当需要多次修改文件时,autodll-webpack-plugin可以明显降低打包的时间,尤其是依赖很多外部库的时候。

3.使用webpack-merge区分生成环境和开发环境:


很多时候,我们都需要针对不同的环境进行不用的操作。

比如在生成环境下分离css到单独文件:
var extractSass = new ExtractTextPlugin({
filename: "[name].[contenthash].css",
disable: process.env.NODE_ENV === "development"
});
在生成环境下要压缩代码:

new UglifyJSPlugin();


在开发环境下使用代理
devServer:{
proxy: {
'api': {
target: 'http://api.douban.com/v2/movie/',
secure: false,
changeOrigin: true
}
}

通常会用process.env.NODE_ENV === "development",并且在package.json中设置环境变量来进行判断,不过当文件大了或者页面需要判断的地方多了之后,配置文件就会充斥着大量三元表达式

可以考虑用webpack-merge将配置文件拆分为3个文件,一个是webpack.common.js,即不管是生产环境还是开发环境都会用到的部分,以及webpack.product.js和webpack.dev.js, 并且使用webpack-merge来合并对象。

common.js

 //webpack.common.js
var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = {
entry: {
app: './src/index.js'
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules:[
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
},
]
},
plugins: [
new HtmlWebpackPlugin({
title: 'test'
})
],
}

dev.js

//开发环境webpack.dev.js
var merge = require('webpack-merge');
var common = require('./webpack.common.js'); module.exports = merge(common, {
module:{
rules:[
{
test: /\.css$/,
use:["style-loader","css-loader"]
}
]
},
devtool: 'inline-source-map',
devServer:{
open:true,
hot: true,
proxy: {
'/api/': {
target: 'http://baidu.com',
secure: false,
changeOrigin: true
}
}
},
})

product.js

//生产环境webpack.product.js
var merge = require('webpack-merge');
var UglifyJSPlugin = require('uglifyjs-webpack-plugin');
var common = require('./webpack.common.js');
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var cleanPlugin = require("clean-webpack-plugin");
var extractSass = new ExtractTextPlugin({
filename: "[name].[contenthash].css",
}); module.exports = merge(common, {
module: {
rules: [{
test: /\.css$/,
use: extractSass.extract({
use: [{
loader: "css-loader"
}, ],
fallback: "style-loader"
})
}] },
devtool: 'source-map',
plugins: [
new cleanPlugin(["dist"]),
new UglifyJSPlugin(),
extractSass,
]
});
在packjson中修改webpack默认配置文件
"scripts": {
"dev": "webpack-dev-server --config webpack.dev.js",
"build": "webpack --config webpack.product.js"
}

通过npm run dev以及npm run build来执行对应的操作。

以上只是一个简单的示例,并不是一定需要拆分成3个文件,如果你的配置足够简单,写成一个webpack.config.js足以。但是,假如你的项目足够庞大,最好还是拆开来写,可以参考vue-cli的脚手架的配置。

webpack2进阶之多文件,DLL,以及webpack-merge的更多相关文章

  1. webpack快速入门——CSS进阶,Less文件的打包和分离

    1.要使用less,首先使用npm安装less服务 cnpm install less --save-dev 还需要安装Less-loader用来打包使用. cnpm install less-loa ...

  2. webpack快速入门——CSS进阶:SASS文件的打包和分离

    1.安裝:因为sass-loader依赖于node-sass,所以需要先安装node-sass cnpm install node-sass --save-dev cnpm install sass- ...

  3. Python爬虫与数据分析之进阶教程:文件操作、lambda表达式、递归、yield生成器

    专栏目录: Python爬虫与数据分析之python教学视频.python源码分享,python Python爬虫与数据分析之基础教程:Python的语法.字典.元组.列表 Python爬虫与数据分析 ...

  4. 未能找到元数据文件**.dll解决办法

    解决方案里有很多项目.生成时提示100多个错误,都是未能找到元数据文件**.dll. 那就清理一下解决方案,一个一个来吧. 生成GateWay.Utilities项目时,虽然提示成功了,却发现bin/ ...

  5. .lib文件 .h文件 .dll文件

    .lib代表的是静态数据连接库,在windows系统中起到链接程序和函数的作用,存放的是函数的是函数调用的信息,是obj文件的集合.相当于linux中的.a或.0. .so文件.lib文件是不对外公开 ...

  6. VS20xx IDE开发应用时_拷贝VS环境的库文件DLL到目标设备上运行的操作步骤

    问题场景: 当用VSIDE开发完一个项目,在部署到目标环境中时,配置文件OK,但是报错需要调试 <1>Deploying Visual C++ library DLLs as shared ...

  7. .h头文件 .lib库文件 .dll动态库文件之间的关系

    .h头文件是编译时必须的,lib是链接时需要的,dll是运行时需要的. 附加依赖项的是.lib不是.dll,若生成了DLL,则肯定也生成 LIB文件.如果要完成源代码的编译和链接,有头文件和lib就够 ...

  8. 由动态库文件dll生成lib库文件(手动生成.def文件,然后使用lib命令编译,非常牛),同理可使用dll生成.a库文件

    本文基于OpenBlas的编译和安装,来说明如何从一个dll文件生成lib库文件. 参考OpenBlas的说明“Howto generate import library for MingW”,和Mi ...

  9. 如何js编译的文件dll对于网页电话

    1. 加入一个项目的解决方案:JSControl 2. 在这个项目中加入js文件(JScript1.js) 脚本的内容: function showAlert(){ alert('Today is a ...

随机推荐

  1. salesforce零基础学习(七十九)简单排序浅谈 篇一

    我们在程序中经常需要对数据列表进行排序,有时候使用SOQL的order by 不一定能完全符合需求,需要对数据进行排序,排序可以有多种方式,不同的方式针对不同的场景.篇一只是简单的描述一下选择排序,插 ...

  2. 8.8.1 Super关键字

    Super关键字 1.super不是引用类型,super中存储的不是内存地址,super指向的不是父类对象. 2.super代表的是当前子类对象中的父类型特征. //通过子类的构造方法去调用父类的构造 ...

  3. 面试 | 商汤科技面试经历之Promise红绿灯的实现

    说在前面 说实话,刚开始在听到这个面试题的实话,我是诧异的,红绿灯?这不是单片机.FPGA.F28335.PLC的实验吗?! 而且还要用Promise去写,当时我确实没思路,只好硬着头皮去写,下来再r ...

  4. 修改windows user 文件夹中的用户名

    假设我们需要将帐户A改名为B.首先我们需要用另一个管理员帐户C登陆系统. 1.在控制面板-〉用户帐户中将帐户A改名为B. 2.打开C:/Users或"用户"文件夹,将文件夹A重命名 ...

  5. [2016-03-15]rabbitmq notes

    安装 系统:CentOS 6 环境: rabbitmq 依赖的Erlang环境包 wget https://www.rabbitmq.com/releases/erlang/erlang-18.1-1 ...

  6. postman 第5节 Runner的使用(转)

    1.首先在postman新建要批量运行的接口文件夹,新建一个接口,并设置好全局变量. 2.然后在Test里面设置好要断言的方法 如: tests["Status code is 200&qu ...

  7. 基于SSM实现的简易员工管理系统(网站上线篇)

    经历无数苦难,好不容易,网站终于上线了.=.=内牛满面ing.chengmingwei.top就是本员工管理系统的主页啦.是的,很简陋,但是毕竟是第一次嘛,所以慢慢来嘛. 如上次所说的(网站简介,见: ...

  8. 10分钟搞懂Tensorflow 逻辑回归实现手写识别

    1. Tensorflow 逻辑回归实现手写识别 1.1. 逻辑回归原理 1.1.1. 逻辑回归 1.1.2. 损失函数 1.2. 实例:手写识别系统 1.1. 逻辑回归原理 1.1.1. 逻辑回归 ...

  9. Linux-grep 命令和find 命令 (6)

    grep与find区别: grep:查找指定目录下过滤文本文件中行数据 find:查找指定目录下文件 grep使用 格式:   grep "text"   *  [选项] 选项: ...

  10. Java中的异常和处理详解

    简介 程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常.异常发生时,是任程序自生自灭,立刻退出终止,还是输出错误给用户?或者用C语言风格:用函数返回值作为执行状态?. ...