一.为何要学习webpackcss
如今的前端网页功能丰富,特别是SPA(single page web application 单页应用)技术流行后,JavaScript的复杂度增长和须要一大堆依赖包,还须要解决SCSS,Less……新增样式的扩展写法的编译工做。因此现代化的前端已经彻底依赖于WebPack的辅助了。html
如今最流行的三个前端框架,能够说和webpack已经紧密相连前端
React.js+WebPackvue
Vue.js+WebPacknode
AngluarJS+WebPackreact
能够看出,不管前端走哪条线,都要有很强的Webpack知识jquery
二. webpack是什么webpack
其实说白了,webpack就是模块打包机。es6
在webpack看来,一切皆模块。Webpack所作的事情就是:分析项目结构,找到js模块以及其余一些浏览器不能直接运行的语言,sass typeScript等,将其转换打包成合适的格式。共浏览器使用。在3.0之后,webpack还有了优化项目的功能web
第一点:打包,webpack多个js文件打包成一个文件。减小服务器压力和下载带宽。减小请求次数和压缩js css img(对原始图片进行压缩处理、调整图片的分辨率和尺寸;服务器开启Gzip压缩功能压缩页面文本)
第二点:转换,可以把less,scss等扩展性语言,以及各类类型的js文件都转换成标准的能被浏览器识别的语言
第三点:优化。Webpack3.0之后,担任着优化和提高性能的责任(好比第三方类库的分离,提取公共代码等)
总结起来,就是打包/转换/优化。话很少说,咱们一块儿来看下怎么使用webpack。若是有不当的地方,欢迎你们纠正,一块儿学习。
三. webpack基础应用
1.安装
webpack安装的两种方式
1. 全局安装:npm install -g webpack
2.本地安装: npm install --save-dev webpack(@version)
webpack 版本查看 :webpack -v
全局安装就是安装到全局目录下(经过 npm config set prefix “目录路径” 来设置。经过 npm config get prefix 来获取当前设置的目录)
可是对于大多数项目咱们推荐安装到本地,缘由是可防止不一样项目依赖不一样版本的 Webpack 而致使冲突。
安装好以后,咱们就能够在项目进行webpack的配置了
2. webpack基本配置-webpack.config.js
module.exports={
entry:{}, // 入口文件的配置项
output:{}, // 出口文件的配置项
module:{}, // 模块:例如解读CSS,图片如何转换,压缩
plugins:[], // 插件,用于生产模版和各项功能
devServer:{} // 配置webpack开发服务功能
}
单入口:
module.exports={
entry:{
entry1: './src/entry.js’
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: ‘bundle.js'
}
}
多入口:
output.path对应一个绝对路径,path.resolve主要是用于设置绝对路径,而且输出文件夹建议是要使用绝对路径的.
module.exports={
entry1:{
entry1: './src/entry.js',
entry2: './src/entry.js’
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: ‘[name].js’
},
……
}
3. 所见即所得之热更新-- devServer
devServer: {
//设置基本目录结构,使用绝对目录
contentBase:path.resolve(__dirname,‘dist’),
//服务器的IP地址,可使用IP也可使用localhost
host:‘localhost’,
//服务端压缩是否开启(自行学习)
compress:true,
//配置服务端口号
port:1717
}
在npm run server 启动后,它是有一种监控机制的(也叫watch)。它能够监控到咱们修改源码,并当即在浏览器里给咱们更新。
Webpack打包以后,运行npm run server 发现只有js 可是能够说明咱们的js打包成功了,可是没有html,新建html,而且将html打包址dist文件夹。这须要借助于一个插件html-webpack-plugin
4. Html打包-- html-webpack-plugin
安装:npm install --save-dev html-webpack-plugin
使用:
const htmlPlugin = require('html-webpack-plugin')
plugins: [
new htmlPlugin({
minify: { removeAttributeQuotes: true },
hash: true,
template: './src/index.html'
})
],
借助于插件-- html-webpack-plugin,能够将咱们的html打包址dist文件夹,在使用以前咱们须要先npm安装
1.require引入插件
2.由于它是一款插件因此咱们须要在plugins中进行这个插件的相关配置。
在配置的时候,须要new一个对象,传入一些参数,minify:对html文件进行压缩,removeAttributeQuotes去掉属性的双引号,hash为true是在js后面增长一段hash值,主要是为了不浏览器缓存的,template打包的模版文件
执行webpack,查看发现script有后缀,而且属性双引号去掉了。
经过这个插件咱们不只能将html文件打包到dist文件夹还能压缩html,那么咱们的js文件怎么压缩呢?
5. Js压缩--uglifyjs-webpack-plugin
若是没有webpack或gulp的话,可能咱们还须要找一个压缩软件或者在线进行压缩,而在webpack中使用默认已经集成的uglifyjs-webpack-plugin插件轻松实现js代码的压缩,因为已经集成,不须要再次安装。用法:
const uglify = require('uglifyjs-webpack-plugin');
plugins:[
new uglify()
],
执行webpack打包,npm run server发现报错了,为何呢?这就涉及到了生产环境和开发环境的区别
由于咱们在开发环境是不须要压缩js的,可是在生产环境中须要,因此uglifyjs适用于生产环境下的,
因此若是咱们在开发环境中作了生产环境作的事情,就会报错了
6. Css文件打包-- style-loader,css-loader
安装:npm install --save-dev css-loader style-loader
使用:
module:{
rules: [{
test: /\.css$/,
use: [ ‘style-loader’, ‘css-loader’ ]
}]
},
Css-loader: 将css文件打包到js中,经常配合style-loader一块儿使用,将css文件打包并插入到页面中
Style-loader: 使用<style>将css-loader内部样式注入到HTML页面
Loaders是Webpack最重要的功能之一,这也是Webpack如此盛行的缘由。经过使用不一样的Loader,从而对不一样的文件格式进行特定处理。
好比说能够把SASS文件的写法转换成CSS,而不在使用其余转换工具;把ES6或者ES7的代码,转换成大多浏览器兼容的JS代码;把React中的JSX转换成JavaScript代码。须要注意的是:全部的Loaders都须要在npm中单独进行安装,并在webpack.config.js里进行配置。Loaders的配置型简单梳理:
test:用于匹配处理文件的扩展名的表达式,这个选项是必须进行配置的;
use:loader名称,就是你要使用模块的名称,这个选项也必须进行配置,不然报错;
include/exclude:手动添加必须处理的文件(文件夹)或屏蔽不须要处理的文件(文件夹)(可选);
query:为loaders提供额外的设置选项(可选)
7.Css中的图片处理-- url-loader
css中添加背景图,执行webpack,图片路径错误
安装:npm install --save-dev file-loader url-loader
使用:{
test: /\.(png|jpg|gif|jpeg|bmp)/i,
use: [{
loader: 'url-loader',
options: {
limit: 500000
}
}]
}
test:/\.(png|jpg|gif)/是匹配图片文件后缀名称
use:是指定使用的loader和loader的配置参数
limit:是把小于500000B的文件打成Base64的格式,写入JS
url-loader会将引入的图片编码,生成dataURl。DataURI是一种提供让外置资源的直接内嵌在页面中的方案。至关于把图片数据翻译成一串字符。再把这串字符打包到文件中,最终只须要引入这个文件就能访问图片了。固然,若是图片较大,编码会消耗性能。所以url-loader提供了一个limit参数,小于limit字节的文件会被转为DataURl,大于limit的还会使用file-loader进行copy。File-loader能够解析项目中的url引入(不只限于css),根据咱们的配置,将图片拷贝到相应的路径,而且修改打包后文件的引用路径,使之指向正确的文件。
8. Css分离--extract-text-webpack-plugin
步骤:
1.安装 npm install --save-dev extract-text-webpack-plugin
2. require引入const extractTextPlugin = require("extract-text-webpack-plugin")
3.Plugins设置: new extractTextPlugin("/css/index.css")
4. 修改css-loader{
test: /\.css$/,
use: extractTextPlugin.extract({
fallback: "style-loader",
use: "css-loader"
})
}
8.Css分离致使图片路径错误-- publicPath
publicPath:是在webpack.config.js文件的output选项中,主要做用就是处理静态文件路径的。
webpack.config.js中声明对象
var website ={
publicPath:http://127.0.0.1:9090/
}
Output配置
output:{
path:path.resolve(__dirname,'dist'),
filename:'[name].js',
publicPath:website.publicPath
}
publickPath是用来存放静态文件的,它的值是咱们的本机ip或者devServer配置的IP和端口
9. img标签添加图片-- html-withimg-loader
1)在img标签中直接引入图片,执行wbbpack命令 —-- 报错
安装:npm install --save html-withimg-loader
使用:Webpack.config.js
{
test: /\.(htm|html)$/i,
use: ['html-withimg-loader']
}
2)将图片打包至image文件夹
options: {
limit: 80000,
outputPath: 'images/'
},
10.消除未使用的CSS --- PurifyCSS
安装:npm i -D purifycss-webpack purify-css
使用:
1)const PurifyCSSPlugin = require("purifycss-webpack")
2)配置plugins
new PurifyCSSPlugin({
paths: glob.sync(path.join(__dirname, 'src/*.html')),
})
注意:
1. purifycss-webpack 安装依赖于purify-css,因此须要都安装
2.这里咱们用到了glob,glob是node中的模块,引入glob主要是用来根据某些规则匹配文件的
3.必须要配合extract-text-webpack-plugin(css分离)插件使用
purifycss-webpack 依赖于 purify-css
paths,主要是需找html模板,purifycss根据这个配置会遍历你的文件,查找哪些css被使用了
Glob:由于咱们须要同步检查html模板,因此咱们须要引入node的glob对象使用。在webpack.config.js文件头部引入glob。
11. Less文件的打包和分离-- less-loader
即:将less转换成css文件进行打包和分离(同css文件分离)
安装less npm install –save-dev less
使用
{
test: /\.less$/,
use: extractTextPlugin.extract({
fallback: "style-loader",
use: ["css-loader", "less-loader"]
})
}
对于less文件的打包和分离和css文件也是几乎同样,只是多了把less转换成css这一步,下载好less-loader 以后就能够了。
webpack的强大除了能够转换less sass以外还可使用babel转换es6 es7 jsx等为普通的js
12支持babel
安装:npm install --save-dev babel-core babel-loader babel-preset- env
使用: webpack.config.js配置
{
test: /\.(jsx|js)$/,
use: {
loader: ‘babel-loader’,
options: { // 选项
presets: [ // 渲染器
”env", "react"]}
},
exclude: /node_modules/
}
注意:后期随着项目的增大可能会有不少渲染器,这是这么写的话可读性不太好了,咱们能够将选项写在.babelrc文件中。
.webpack.config.js
{
test: /\.(jsx|js)$/,
use: {
loader: ‘babel-loader’
},
exclude: /node_modules/
}
.babelrc
{
"presets": [
"react",
”env"
]
}
11. 抽离第三方类库
Webpack.config.js
entry:{
entry:'./src/entry.js',
jquery:'jquery',
vue:'vue
'},
new webpack.optimize.CommonsChunkPlugin({
name:[‘jquery’,‘vue’],
filename:"assets/js/[name].js",
minChunks:2
}),
12. 提取公共代码--CommonsChunkPlugin
步骤:
1.将全部页面都依赖的库好比:vue react react-dom等提取到一个单独的文件,通常叫作base.js(基础运行环境)
2.剔除各个页面中的base.js以后的代码,再找出它们以来的公共部分的代码,放到common.js
3.将各个页面生成单独的文件,这些文件将不包含base.js,common.js中的部分,只包含个页面单独须要的部分代码
具体实现须要借助于Webpack 内置的用于提取多个 Chunk 中公共部分的插件 CommonsChunkPlugin
大型网站一般会由多个页面组成,没个页面都是一个独立的单页应用。可是因为全部页面采用的都是相同的技术栈,可能就会致使有不少重复的代码。若是每一个页面的代码都把这些公共的部分包含进去,会形成一些问题。
1)相同资源重复加载,浪费用户流量和服务器成本;2)页面须要加载的资源太大,致使页面首屏加载缓慢,影响用户体验
那么若是咱们能将公共的代码提取出来,那么用户在访问其中一个网页的时候,页面的公共代码文件就已经被浏览器缓存起来,用户再访问其余页面的时候,公共代码不会从新加载而是从缓存中获取。如此,虽然首屏访问得不到优化,可是后续页面速度大大提高,而且减小了网络流量和服务器成本。那么怎么提取公共代码呢???
1.将全部页面都依赖的库好比:vue react react-dom等提取到一个单独的文件,通常叫作base.js(基础运行环境)
2.剔除各个页面中的base.js以后的代码,再找出它们以来的公共部分的代码,放到common.js
3.将各个页面生成单独的文件,这些文件将不包含base.js,common.js中的部分,只包含个页面单独须要的部分代码
在线上文件中,对静态文件的文件名都附加根据文件内容计算出的hash值,好比base_123a.js,以长期缓存,只要不升级基础库的版本,base的内容就不会变化,hash就不会更新,缓存也不会更新,每次更新代码common.js和js会因文件内容变化而致使hash值被更新。
每次发布浏览器都会使用被缓存的 base.js 文件,而不用去从新下载 base.js 文件。 因为 base.js 一般会很大,这对提高网页加速速度能起到很大的效果。
const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
new CommonsChunkPlugin({
chunks: [‘a’, ‘b’], // 从哪些 Chunk 中提取,默认从全部已知chunk获取
name: 'common’ // 提取出的公共部分造成一个新的 Chunk
})
require('webpack/lib/optimize/CommonsChunkPlugin');
new CommonsChunkPlugin({
chunks: [‘a’, ‘b’], // 从哪些 Chunk 中提取,默认从全部已知chunk获取
name: 'common’ // 提取出的公共部分造成一个新的 Chunk
})
以上是将a,b的公共代码提取到了common中,接下来咱们还须要从common中,提取出基础运行库。
须要如下操做:
1)首先须要在项目中写一个base.js来描述项目因此来的模块,好比:
// 全部页面都依赖的基础库
import 'react';
import 'react-dom';
// 全部页面都使用的样式
import './base.css';
2)再修改webpack
module.exports = {
entry: {
base: './base.js'
},
};
new CommonsChunkPlugin({
// 从 common 和 base 两个现成的 Chunk 中提取公共的部分
chunks: ['common', 'base'], // 把公共的部分放到 base 中 name: 'base'
})
<script src="base.js"></script>
<script src="common.js"></script>
<script src="a.js"></script>
13.打包后如何调试
主要有如下几种方式:
1)source-map:生成独立map文件,包含行列信息(信息最详细完整)
2)cheap-module-source-map:生成独立map文件,只包含行信息
3)eval-source-map:js文件内生成sourcemap,包含行列信息
4)cheap-module-eval-source-map:就是文件内生成sourcemap,只包含行信息
注意:1)source-map模式下会输出质量最高最详细的source Map ,可是会形成构建速度缓慢,在开发过程当中若是频繁修改,会增长等待时间;
2)source Map会被暴漏出去,因此在生产环境下不建议使用source-map;
3)建议在开发环境下使用cheap-module-eval-source-map或者eval-source-map,开发环境下使用hidden-source-map,可生成最详细的source Map,但不会暴漏源码