webpack基础运用
// webpack4中除了平常装置webpack以外,须要再零丁安一个webpack-cli
npm i webpack webpack-cli -D
基础敕令行
webpack <entry> [<entry>] <output>
设置文件运用
直接输入webpack,默许实行: webpack.config.js or webpackfile.js文件;
假如想自定义文件名,运转:webpack –config webpack.conf.dev.js
打包js
// ESmodule
export default function(a,b){
return a+b
}
import sum from './sum'
// common.js范例
module.exports = function(a,b){
return a-b
}
var minus = require('./minus')
// AMD范例,多了两个bundle,异步加载
//amd范例
define(function(require, factory) {
'use strict';
return function(a,b){
return a*b
}
});
require(['./muti'],function(muti){
console.log('muti,23,24='+muti(23,24))
})
console.log('sum,23,24='+sum(23,24))
console.log('minus,23,24='+minus(23,24))
编译 ES 6/7
- 装置babel-loader, babel-core, babel-preset-env
npm install –save-dev babel-loader babel-core babel-preset-env
babel-loader:在import或加载模块时,对es6代码举行预处置惩罚,es6语法转化为es5语法。
babel-core:许可我们去挪用babel的api,能够将js代码剖析成ast(笼统语法树),轻易各个插件剖析语法举行相应的处置惩罚.
babel-preset-env:为了通知babel只编译同意的内容,相当于babel-preset-es2015, es2016, es2017及最新版本。经由过程它能够运用最新的js语法。
- 设置webpack.config.js
module.exports = {
entry:{
app:'./app.js'
},
output:{
filename:'[name].[hash:5].js'
},
module:{
rules:[
{
test:/\.js$/,
use:{
loader:'babel-loader',
options:{
presets:[
// 最新的版本
['@babel/preset-env',{
targets:{// 支撑目的,数据来源于‘can i use’网站
browsers:['> 1%','last 2 versions']
//chrome:'52'
}
}]
]
}
},
//消除相干文件
exclude:'/node_modules/'
}
]
}
}
个中,exclude是定义不愿望babel处置惩罚的文件。targets是presets的一些预设选项,这里示意将js用于阅读器,只确保占比大于1%的阅读器的特征,主流阅读器的最新两个主版本。
更多与设置有关的信息,能够参考:
babel env preset设置,
browserlist预设置
由于babel-preset设置选项较多,我们平常能够在根目次下竖立.babelrc文件,特地用来安排babel preset设置,这是一个json文件。能够将上述设置修正以下:
//.bablerc文件
{
"presets": [
['env',{
"targets": {
"browsers": ['> 1%', 'last 2 versions']
}
}]
]
}
//原webpack.config.js文件
module: {
rules: [
{
test: /\.js$/,
use: {
loader: 'babel-loader'
},
exclude: '/node_modules/'
}
]
}
babel-polifill
在上面的babel设置中,babel只是将一些es6,es7-8的语法转换成相符目的的js代码,然则假如我们运用一些特征或要领,比方Generator, Set, 或许一些要领。babel并不能转换为低版本阅读器识别的代码。这时刻就须要babel-polifill。
简朴的说,polifill就是一个垫片,供应了一些低版本es规范对高等特征的完成。运用polifill的要领以下:
npm install --save babel-polifill
然后在运用进口引入polifill,要确保它在任何其他代码/依靠声明前被挪用。
//CommonJS module
require('babel-polyfill');
//es module
import 'babel-polifill';
在webpack.config.js中,将babel-polifill到场entry数组中:
entry: ["babel-polifill", "./app.js"]
比拟于runtime-transform,polifill用于运用开辟中。会增加相应变量到全局,所以会污染全局变量。
更多设置参考:babel-polifill
完全代码以下:
const path = require('path');
module.exports = {
//entry为进口,webpack从这里最先编译
entry: [
"babel-polyfill",
path.join(__dirname, './src/index.js')
],
//output为输出 path代表途径 filename代表文件名称
output: {
path: path.join(__dirname, './bundle'),
filename: 'bundle.js'
},
//module是设置一切模块要经由什么处置惩罚
//test:处置惩罚什么范例的文件,use:用什么,include:处置惩罚这里的,exclude:不处置惩罚这里的
module: {
rules: [
{
test: /\.js$/,
use: ['babel-loader'],
include: path.join(__dirname , 'src'),
exclude: /node_modules/
}
]
},
};
runtime-transform插件
runtime transform也是一个插件,它与polifill有些相似,但它不污染全局变量,所以常常用于框架开辟。
装置:
*npm install –save-dev babel-plugin-transform-runtime
npm install –save babel-runtime*
用法:
将下面内容增加到.bablerc文件中
{
"plugins": ["transform-runtime"]
}
更多设置参考:bable-runtime-transform插件
运用 loader 处置惩罚 CSS
1 . 装置处置惩罚 css 相干 loader
// css-loader让你能import css , style-loader能将css以style的情势插进去
$ npm install --save-dev css-loader style-loader
module.exports = {
plugins: [require('autoprefixer')] // 援用该插件即可了
}
然后在webpack里设置postcss-loader
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader', 'postcss-loader']
}
]
}
}
2 . 装置 less 相干
npm install --save-dev less less-loader
3 . 增加CSS3前缀
经由过程postcss中的autoprefixer能够完成将CSS3中的一些须要兼容写法的属性增加相应的前缀,如许省去我们不少的时刻
npm i postcss-loader autoprefixer -D
建立 postcss.config.js 到场以下代码
module.exports = {
plugins: {
'postcss-cssnext': {}
}
}
4 . 完成
src/app.css
body {
background: pink;
}
src/app.js
import css from './app.css';
console.log("hello world");
// 处置惩罚递次从右到左 less -> postcss -> css -> style
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader' ]
}
5.用 mini-css-extract-plugin 把 CSS 星散成文件
npm install --save-dev mini-css-extract-plugin
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader']
}
]
new MiniCssExtractPlugin({
filename: "[name].css",// 指定打包后的css
chunkFilename: "[id].css"
}),
6.紧缩与优化
打包 css 今后检察源码,我们发明它并没有帮我们做代码紧缩,这时刻候须要运用 optimize-css-assets-webpack-plugin 这个插件,它不仅能帮你紧缩 css 还能优化你的代码。
npm install --save-dev optimize-css-assets-webpack-plugin
const optimizeCss = require('optimize-css-assets-webpack-plugin');
//设置
optimization: {
minimizer: [new OptimizeCSSAssetsPlugin()];
}
如上图测试用例所示,由于optimize-css-assets-webpack-plugin这个插件默许运用了 cssnano 来作 css 优化,
所以它不仅紧缩了代码、删掉了代码中无用的解释、还去除了冗余的 css、优化了 css 的誊写递次,优化了你的代码 margin: 10px 20px 10px 20px; =>margin:10px 20px;。同时大大减小了你 css 的文件大小。更多优化的细节见文档。
插件
天生HTML插件
装置插件npm install –save-dev html-webpack-plugin 设置 webpack.config.js
npm install --save-dev html-webpack-plugin
const htmlWebpackPlugin = require('html-webpack-plugin');
...
plugins: [
new htmlWebpackPlugin({
filename: "index.html", //打包后的文件名
template: path.join(__dirname , "./src/index.html"), // 用哪一个html作为模板,在src目次下建立一个index.html页面当作模板来用
hash: true, // 会在打包好的bundle.js背面加上hash串
})
],
假如须要多页面开辟,能够如许写:
let path = require('path');
let HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
// 多页面开辟,怎样设置多页面
entry: {
index: './src/index.js',
login: './src/login.js'
},
// 出口文件
output: {
filename: '[name].js',
path: path.resolve('dist')
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'index.html',
chunks: ['index'] // 对应关联,index.js对应的是index.html
}),
new HtmlWebpackPlugin({
template: './src/login.html',
filename: 'login.html',
chunks: ['login'] // 对应关联,login.js对应的是login.html
})
]
}
清算打包文件插件
$ npm i clean-webpack-plugin --save-dev
const CleanWebpackPlugin = require('clean-webpack-plugin');
...
plugins: [
...
new CleanWebpackPlugin(['bundle']) //传入清晰途径
]
提取大众代码
缘由和上风
- 缘由
1.雷同的资本被反复的加载,糟蹋用户的流量和服务器的本钱;
2.每一个页面须要加载的资本太大,致使网页首屏加载迟缓,影响用户体验。 - 长处
1.削减收集传输流量,下降服务器本钱;
2.虽然用户第一次翻开网站的速率得不到优化,但今后接见别的页面的速率将大大提拔。
optimization
在webpack4之前,提取大众代码都是经由过程一个叫CommonsChunkPlugin的插件来办到的。到了4今后,内置了一个如出一辙的功用,而且起了一个好听的名字叫“优化”
下面我们就来看看怎样提取大众代码
// 假定a.js和b.js都同时引入了jquery.js和一个写好的utils.js
// a.js和b.js
import $ from 'jquery';
import {sum} from 'utils';
那末他们两个js中个中大众部份的代码就是jquery和utils里的代码了
能够针对第三方插件和写好的大众文件
module.exports = {
entry: {
a: './src/a.js',
b: './src/b.js'
},
output: {
filename: '[name].js',
path: path.resolve('dust')
},
// 提取大众代码
+ optimization: {
splitChunks: {
cacheGroups: {
vendor: { // 抽离第三方插件
test: /node_modules/, // 指定是node_modules下的第三方包
chunks: 'initial',
name: 'vendor', // 打包后的文件名,恣意定名
// 设置优先级,防备和自定义的大众代码提取时被掩盖,不举行打包
priority: 10
},
utils: { // 抽离本身写的大众代码,utils这个名字能够随便起
chunks: 'initial',
name: 'utils', // 恣意定名
minSize: 0 // 只需超越0字节就天生一个新包
}
}
}
+ },
plugins: [
new HtmlWebpackPlugin({
filename: 'a.html',
template: './src/index.html', // 以index.html为模板
+ chunks: ['vendor', 'a']
}),
new HtmlWebpackPlugin({
filename: 'b.html',
template: './src/index.html', // 以index.html为模板
+ chunks: ['vendor', 'b']
})
]
}
经由过程以上设置,能够把引入到a.js和b.js中的这部份大众代码提取出来,以下图所示
webpack-dev-server设置
装置 webpack-dev-server
npm install --save-dev webpack-dev-server
webpack.config.js 增加设置
...
devServer: {
contentBase: path.join(__dirname, 'bundle'), //启动途径
host:'localhost', //域名,默许是localhost
port: 8018, //端口号
open: true, //自动翻开阅读器
hot: true //开启热更新
}
当然在npm run dev敕令下,打包的文件存在于内存中,并不会产生在dist目次下
- 热更新和自动革新的区分
设置devServer的时刻,假如hot为true,就代表开启了热更新
But这并没那末简朴,由于热更新还须要设置一个webpack自带的插件而且还要在重要js文件里搜检是不是有module.hot
下面就让我们直接看下代码是怎样完成的
// webpack.config.js
let webpack = require('webpack');
module.exports = {
plugins: [
// 热更新,热更新不是革新
new webpack.HotModuleReplacementPlugin()
],
devServer: {
contentBase: './dist',
hot: true,
port: 3000
}
}
// 此时还没完虽然设置了插件和开启了热更新,但现实上并不会见效
// index.js
let a = 'hello world';
document.body.innerHTML = a;
console.log('这是webpack打包的进口文件');
// 还须要在重要的js文件里写入下面这段代码
if (module.hot) {
// 完成热更新
module.hot.accept();
}
编译图片
- file-loader
对一些对象作为文件来处置惩罚,然后能够返回它的URL。
$ npm install --save-dev file-loader
test: /\.(gif|png|jpe?g|svg)$/i,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]', // 文件名和扩展名
outputPath: 'images/'
}
},
- url-loader
npm i file-loader url-loader -D
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: ExtractTextWebpackPlugin.extract({
use: 'css-loader',
publicPath: '../'
})
},
{
test: /\.(jpe?g|png|gif)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 8192, // 小于8k的图片自动转成base64花样,而且不会存在实体图片
outputPath: 'images/' // 图片打包后寄存的目次
}
}
]
}
]
}
}
- 剖析 html 代码内里 img 的标签
html-loader: html 变成导出成字符串的过程当中,还能举行紧缩处置惩罚(minimized)
$ npm install --save-dev html-loader
...
{
test: /\.(gif|png|jpe?g|svg)$/i,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/'
}
},
]
},
// 下面几行才是 html-loader 的设置内容
{
test: /\.html$/,
use: [ {
loader: 'html-loader',
options: {
minimize: true
}
}],
}
...
- 紧缩图片
image-webpack-loader:紧缩图片文件
$ npm install image-webpack-loader --save-dev
{
test: /\.(gif|png|jpe?g|svg)$/i,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/'
}
},
{
loader: 'image-webpack-loader',
options: {
bypassOnDebug: true,
}
}
]
},
{
test: /\.html$/,
use: [ {
loader: 'html-loader',
options: {
minimize: true
}
}],
}
resolve剖析
在webpack的设置中,resolve我们常用来设置别号和省略后缀名
module.exports = {
resolve: {
// 别号
alias: {
$: './src/jquery.js'
},
// 省略后缀
extensions: ['.js', '.json', '.css']
},
}
打包速率
webpack 4 在项目中现实测了下,广泛能进步 20%~30%的打包速率。
起首你须要晓得你现在打包慢,是慢在那里。
我们能够用 speed-measure-webpack-plugin 这个插件,它能监控 webpack 每一步操纵的耗时。以下图:
能够看出实在大部份打包消费的时刻是在Uglifyjs紧缩代码。和前面的提拔热更新的切入点差不多,检察source map的准确与否,exclude/include的准确运用等等。