关于wepack的使用总结以及优化探讨
一、前言
不知不觉,webpack版本已经到4.0了。使用它也有很长一段时间了,回头看看,自己木有总结webpack方面的知识,现在有空起个头,主要是总结自己常用的配置和一下优化的探讨,以后有啥想法也直接写到这里来。
二、开始
webpack做啥的,怎么配置?和gulp、grunt等构件工具有什么区别?这些就跳过了,当初也是直接看官方文档的,摸爬滚打走过来的。可以参考:
5 、 https://www.jianshu.com/p/b9bf995f3712
三、实际项目中解析
3.1、本项目支持的功能
1 对less编译
2 支持es6语法支持
3 编译.vue组件,并自动内联组件样式
4 图片打包,包括对html内图片处理(利用html-loader和es6字符串模板),对小图片生成base64
5 利用htmlWebpackPlugin动态拼接html 的公共部分和内容部分,引入相应css/js资源,并构建到指定目录, 对ejs模板支持
6 对js内依赖的css分离并压缩
7 对js引用的公共模块抽取分离成单独文件
8 区分开发环境和生产环境
9 js 压缩
10 静态文件(css/js/img)hash版本支持
11 清除目标文件目录
12 eslint支持并实现自动修复部分问题
13 vue接口请求axios支持
14 热更新,自动编译并刷新浏览器
3.2、目录结构
|__ html
|__ dist
|__ income.html
|__ index.html
|__ src
|__ income
|__ income.ejs
|__ income.js
|__ index
|__ index.ejs
|__ index.js
|__ layouts
|__ footer.ejs
|__ header.ejs
|__ layout.ejs
|__ layout.js
|__ side-menu.e
|__ top-nav.ejs
|__ dist
|__ css
|__ img
|__ js
|__ income.js
|__ index.js
|__ manifest.js
|__ vendors.js
|__ src
|__ css
|__ img
|__ js
|__ component
|__ App.vue
|__ income.js
|__ index.js
|__ lib
|__ axios.min.js
|__ layer.js
|__ vue.js
|__ vue.min.js
|__ mock
|__ node_modules
|__ webpack-config
|__ .eslintrc.dev.js
|__ .eslintrc.js
|__ postcss.config.js
|__ resolve.config.js
|__ package.json
|__ .babelrc
|__ .eslintrc.js
四、入口entry
var entries = getEntry('./src/**/*.js') // 获得入口js文件
entries.vendors = ['vue','axios'] module.exports = {
/* 输入文件 */
entry: entries
}
通常我们的项目中有大量的js入口文件,基本一个功能页面有一个js,这时我们的 entry 文件为一个对象格式
entries 为: {
income: './src/js/income.js',
index: './src/js/index.js',
vendors: [ 'vue', 'axios' ]
}
key 值为对应模块的别名,webpack会依次处理这些模块。
vendors 为公共模块,这里我们把vue, axios设置为公共模块,供下面进行提取公共模块操作。
之所以可以直接写vue, axios,是因为我们在 alias 里设置了别名:
var path = require('path') module.exports = {
// 模块别名的配置,为了使用方便,一般来说所有模块都是要配置一下别名的
alias: {
'vue': path.resolve(__dirname, '../src/js/lib/vue.min.js'),
'axios': path.resolve(__dirname, '../src/js/lib/axios.min.js')
}
}
这里的 path.resolve 作用是把相对路径转为绝对路径,假设我项目建在d:/demo 目录下,
_dirname: d:\demo path.resolve(__dirname, '../src/js/lib/vue.min.js'): d:\demo\src\js\lib\vue.min.js
getEntry() 为获取文件路径的自定义函数:
/***** 获取文件列表:输出正确的js和html路径 *****/
var glob = require('glob') function getEntry(globPath) {
var entries = {}, basename glob.sync(globPath).forEach(function (entry) {
//排出layouts内的公共文件
if(entry.indexOf('layouts') == -1 && entry.indexOf('lib') == -1){
basename = path.basename(entry, path.extname(entry))
entries[basename] = entry
}
})
return entries
}
通常webpack的entry入口文件,是功能性页面的js,对于js库等文件不需要列入入口文件进行处理。所以这里对lib文件夹进行了排除。layouts文件夹为获取html路径时需要排除的文件路径。
五、output介绍
module.exports = {
output: {
/* 输出目录,没有则新建 */
path: path.resolve(__dirname, './dist'),
/* 静态目录,可以直接从这里取文件 */
publicPath: 'http://www.xxx.com/dist/',
/* 文件名 */
filename: 'js/[name].js?v=[chunkhash:8]'
}
}
publicPath: 如果有这项,则html中的引用的js路径会加上publicPath,即 http://www.xxx.com/dist/js/[name].js?v=[chunkhash:8]
filename: 这里可以自定义输出后的文件名,加上版本号
[name] :输入模块的别名
[chunkhash] : 模块的hash值,":8"代表保留8位hash值
[hash] : 整个编译环境的hash值
六、module介绍
Webpack有一个不可不说的优点,它把所有的文件都都当做模块处理,JavaScript代码,CSS和fonts以及图片等等通过合适的loader都可以被处理。
webpack利用各种loader来把不同格式的文件封装成模块加载到js内,比如css-loader, vue-loader,下面,只列举一部分。
6.1、babel-loader
es6语法目前很多浏览器不支持,我们需要将其转化为大部分浏览器支持的es5语法,这就需要babel-loader
{
test: /\.js$/,
loader: 'babel-loader',
exclude: ['node_modules','./src/js/lib','./src/js/component']
}
6.2、 css有关的loader
css-loader style-loader post-loader less-loader
{
test: /\.css$/,
use: ['style-loader', 'css-loader', 'postcss-loader']
},
{
test: /\.less$/,
use: ExtractTextPlugin.extract(['css-loader','postcss-loader','less-loader'])
}
对于有多个loader时,webpack v2也废弃了v1的 " !" 连接,改为数组形式,且不能省略 " -loader " 以免造成名称混乱意思模糊,执行顺序为从右到左
postcss-loader:为集合处理css各种问题的平台,其上面有各种插件来处理css,我们这里只用到了autoprefixer插件,后面插件部分会详解
style-loader:可以将css以style内联方式嵌入到html页面
css-loader:使你能够使用类似@import 和 url(...)的方法实现 require()的功能
ExtractTextPlugin:提取css, 后面插件部分会进行详解
6.3、css module:
把JS的模块化思想带入CSS中来,通过CSS模块,所有的类名,动画名默认都只作用于当前模块。Webpack对CSS模块化提供了非常好的支持,只需要在CSS loader中进行简单配置即可,然后就可以直接把CSS的类名传递到组件的代码中,这样做有效避免了全局污染。具体的代码如下:
module.exports = { ... module: {
rules: [
{
test: /(\.jsx|\.js)$/,
use: {
loader: "babel-loader"
},
exclude: /node_modules/
},
{
test: /\.css$/,
use: [
{
loader: "style-loader"
}, {
loader: "css-loader",
options: {
modules: true, // 指定启用css modules
localIdentName: '[name]__[local]--[hash:base64:5]' // 指定css的类名格式
}
}
]
}
]
}
};
6.4、文件图片loader
{
test: /\.(png|jpg|gif)$/,
loader: 'url-loader?limit=5120&name=img/[name].[ext]?v=[hash:8]'
}
6.5、字体loader
{
test: /\.(ttf|ttc|eot|svg|woff(2))$/,
loader: 'file-loader',
options:{
name: function(p){
let tem_path = p.split(/\\fonts\\/)[1];
tem_path = tem_path.replace(/\\/g,'/');
return 'fonts/'+tem_path + '?v=[hash:8]';
}
}
}
七、插件plugin
插件是用来拓展Webpack功能的,它们会在整个构建过程中生效,执行相关的任务。
Loaders和Plugins常常被弄混,但是他们其实是完全不同的东西,可以这么来说,loaders是在打包构建过程中用来处理源文件的(JSX,Scss,Less..),一次处理一个,插件并不直接操作单个文件,它直接对整个构建过程其作用。
使用方法一般如下:
module: {},
plugins: [
new ExtractTextPlugin('css/[name].css?v=[contenthash:6]'),
new webpack.LoaderOptionsPlugin({
options: {
eslint: require( './webpack-config/.eslintrc.js'),
postcss: require( './webpack-config/postcss.config.js')
},
})
]
webpack声明插件的方式可以像上面的写法也可以如下方式:
module.exports.plugins = module.exports.plugins.concat([
//压缩css代码
new OptimizeCssAssetsPlugin({
assetNameRegExp: /\.css/g,
cssProcessor: require('cssnano'),
cssProcessorOptions: { discardComments: {removeAll: true } },
canPrint: true
}),
//压缩JS代码
new webpack.optimize.UglifyJsPlugin({
output: {
comments: false, // 去掉注释内容
}
})
])
7.1、extract-text-webpack-plugin 插件
默认情况下,js依赖引入css,编译后,css被加在js中,如果我们想把css提取出一个单独的文件,可以使用这个插件,并可以对提取出的css进行自定义命名和加版本hash值
new ExtractTextPlugin('css/[name].[contenthash:8].css'),
7.2、optimize-css-assets-webpack-plugin 插件
压缩css文件,对从js中提取出的css文件亦有效
注意:此插件是在css被提取出来加了hash值后进行处理,如果css文件提出来后被命名为 css/[name].css?v=[contenthash:8] 形式,插件的使用如下
new OptimizeCssAssetsPlugin({
assetNameRegExp: /\.css/g, //注意不要写成 /\.css$/g, 否则匹配不到css文件会导致压缩不成功
cssProcessor: require('cssnano'),
cssProcessorOptions: { discardComments: {removeAll: true } },
canPrint: true
})
7.3、webpack-plugin 插件
用于根据模板组合html各个部分,并插入对应引用的js,对前后端分离贡献颇多,功能强大会有专门的篇章来介绍
7.4、CommonsChunkPlugin 插件
提取js的公共模块,此插件为webpack自带的插件
new webpack.optimize.CommonsChunkPlugin({
names: ['vendors', 'manifest'], // 公共模块的名称
//filename: 'js/[name]-[chunkhash:6].js', // 公共模块的名称
chunks: 'vendors', // chunks是需要提取的模块
minChunks: Infinity //公共模块最小被引用的次数
})
通常我们的js可能会引入一些公共js文件,包括一些类库,如果都打包在一个js中,这个js会变得非常庞大,而且一旦我们功能页面的js有变化,会导致打包后的js版本号进行更新然后重新加载,这个代价有些大,所以我们会考虑把一些公共的js文件提取出一个单独的文件,这样在第一次访问的时候会加载,之后就可以缓存下来,减少服务器请求的压力并提高加载速度。
7.5 CleanWebpackPlugin插件
保证买次编译之后目标文件中只保留最新的文件
new CleanWebpackPlugin(['dist'])
------------有时间再添加了------------
八、一些优化探索
关于wepack的使用总结以及优化探讨的更多相关文章
- CSS性能优化探讨
大部分前端开发人员都不关心CSS性能优化,其实对于一个复杂的页面来说,高效的选择器还是可以带来一定的性能提升的. 1. CSS 选择器 浏览器是“从右往左”来分析 class 的,它的匹配规则是从右向 ...
- Webpack 打包之体积优化
谈及如今欣欣向荣的前端圈,不仅有各类框架百花齐放,如Vue, React, Angular等等,就打包工具而言,发展也是如火如荼,百家争鸣:从早期的王者Browserify, Grunt,到后来赢得宝 ...
- [转] Webpack 打包优化之体积篇
谈及如今欣欣向荣的前端圈,不仅有各类框架百花齐放,如Vue, React, Angular等等,就打包工具而言,发展也是如火如荼,百家争鸣:从早期的王者Browserify, Grunt,到后来赢得宝 ...
- Webpack 打包优化之体积篇
谈及如今欣欣向荣的前端圈,不仅有各类框架百花齐放,如Vue, React, Angular等等,就打包工具而言,发展也是如火如荼,百家争鸣:从早期的王者Browserify, Grunt,到后来赢得宝 ...
- Python Flask高级编程之RESTFul API前后端分离精讲 (网盘免费分享)
Python Flask高级编程之RESTFul API前后端分离精讲 (免费分享) 点击链接或搜索QQ号直接加群获取其它资料: 链接:https://pan.baidu.com/s/12eKrJK ...
- System.out.printf使用以及注意点
一.System.out.printf格式化输出 1.常用控制符 控制符 说明 %d 按十进制整型数据的实际长度输出. %ld 输出长整型数据. %md m 为指定的输出字段的宽度.如果数据的位数小于 ...
- 《MySQL必知必会》学习笔记——第30章 改善性能
本章将付息与MySQL性能有关的某些要点. 30.1 改善性能 数据库管理员把他们生命中的相当一部分时间花在了调整.试验以改善DBMS性能之上.在诊断英勇的滞缓现象和性能问题时,性能不良的数据库(以及 ...
- 【MySQL 基础】MySQL必知必会
MySQL必知必会 简介 <MySQL必知必会>的学习笔记和总结. 书籍链接 了解SQL 数据库基础 什么是数据库 数据库(database):保存有组织的数据的容器(通常是一个文 件或一 ...
- 移动 H5 首屏秒开优化方案探讨
转载bang大神文章,原文<移动 H5 首屏秒开优化方案探讨>,此文仅仅用做自学与分享! 随着移动设备性能不断增强,web 页面的性能体验逐渐变得可以接受,又因为 web 开发模式的诸多好 ...
随机推荐
- 重读<<大话设计模式>>读书笔记一
面向对象编程几大原则: 1.简单工厂模式 解读:根据不同条件,动态创建合适的对象. 目的: 解决对象创建问题 举例: 计算器根据不同情况,创建适合的对象来处理数据. 2.策略模式 解读:也是根据不同的 ...
- Visual Studio2013 配置opencv3.3.0 x64系统
注:小白一个,第一次写博客,可能会有一些理解上的错误,只此记录自己测试成功的坎坷之路,已备以后查看,同时给有需要之人. 我是win10 64 位,之前安装了visual studio 2013, 现在 ...
- 登录服务器失败 IP 统计和处理方法
一.登录ssh失败次数统计 1)错误的打开方式 awk '/Failed password/ {print $(NF-3)}' secure |sort -n |uniq -c|sort -n |ta ...
- 别人的Linux私房菜(5)首次CentOS7与帮助等
ctrl alt F1-F6切换终端tty1-6,其中,F1的终端带有用户界面. 在终端登录后,输入startx启动个人图形界面.(启动有一些条件限制,如没有其他的X Window启用,已经安装,并具 ...
- javascript字符串方法总结
一.单引号字符串内部可以使用双引号,双引号字符串内部也可以使用单引号 "hello 'world'" 'welcome "to" js' 二.多行和转义 如果要 ...
- vue里router-link标签设置动态路由的3个方法
1.to绑定data里面的一个值 2.to绑定一个对象,用name 3.to绑定一个对象,用path 例子: <router-link :to="home"><s ...
- jdk8中关于操作集合的一些新特性,遍历和排序操作
jdk8增加了不少新的东西,在集合操作这块,就有如 lamda表达式,stream,sort,optional等新的类,主要涉及遍历和排序等方面,新特性提升了不少性能,我们开发就是要拥抱新事物,守着老 ...
- 关于Runtime.getRuntime().exec()产生阻塞的2个陷阱
本文来自网易云社区 背景 相信做java服务端开发的童鞋,经常会遇到Java应用调用外部命令启动一些新进程来执行一些操作的场景,这时候就会使用到Runtime.getRuntime().exec(), ...
- Vue自定义指令,ref ,sync,slot
一.自定义指令 vue中可以自己设置指令,通过directive来实现,有2种创建方式,一种是局部创建,一种是全局创建. 第一种:局部创建 如果想注册局部指令,组件中也接受一个 directives ...
- 我自己的sublime3环境
概述 我本来一直用的别人自带的破解版sublime3,自带插件. 前几天看<程序员修炼之道>,其中谈到了最好精通一种编辑器,我觉得说的很有道理,于是重新下了最新版的sublime3,一步步 ...