webpack 根底篇
npm 卸载包
npm uninstall 包名 npm unistall webpack -g -global 全局示意哪都能用
初始化我的项目
yarn init -y ||npm init -y
webpack 装置
- webpack4.0
- 装置本地的 webpack
- yarn add webpack webpack-cli -D||npm install webpack webpack-cli -D
- -D 示意 development 开发环境
webpack 能够进行 0 配置
目录构造
src
- index.js
- 间接运行 npx webpack
- 打包工具 -> 输入后的后果(js 模块)
- 打包(间接 js 的模块化)
手动配置 webpack(0配置很弱)
- [x] 默认配置文件的名字是 webpack.config.js/webpackfile.js 通常应用 webpack.config.js
- webpack 是基于 node 编写的
- 有webpack.config.js运行命令就会走咱们本人写的配置
- --config 来指定webpack运行哪个文件
* 开发服务器配置
- yarn add webpack-dev-server -D||npm install webpack-dev-server -D
devServer:{ port:3000, #端口号 contentBase:'./dist', #目录 如果没有dist文件夹 会在内存外面主动创立 open:true, #是否主动关上浏览器 progress:true, #显示进度条 compress:true #是否开启gzip压缩 proxy:{ //能够配置跨域 } }
* 配置脚本命令 package.json
- "scripts": { } 这外面配置的命令叫做脚本
- -- config 指定默认运行文件是哪个
- "build": "webpack --config webpack.config.js", npm run build = npx webpack 会打包
- "dev": "webpack-dev-server" npm run dev 会启动一个服务器 默认会关上localhost:8080
- "start":"npm run dev"
- 这样就能够通过 npm run dev/npm run build 执行相干的命令
* 配置进口入口
- [x]entry 入口 能够是相对路径
- [x]output 进口 输入
- path 输入门路 必须是绝对路径 打包过后的文件夹名称
- filename:打包当前的文件名称
module.exports={ entry:'./src/index.js', output:{ path:path.resolve(__dirname,'dist'), filename:'bundle[hash:6].js', publicPath:'http://www.baidu.com' }}
间接给文件加 hash 值(避免浏览器缓存)
filename:'bundle[hash].js'能够用:前面跟数字设置hash值的长度filename:'bundle[hash:8].js'
* 配置打包环境
- mode 的值 2 个值 development 和
production
- [x] development 开发环境 代码没压缩 有正文
- [x] production 生产环境 代码压缩 没有正文
module.exports={ mode:'development', ...}
解决 html 主动引入js
- plugin 插件 plugins 插件们 数组[插件1,插件2,插件3]
src
- index.js
- index.html
- [x] yarn add html-webpack-plugin -D||npm install html-webpack-plugin -D
- 当有插件的时候须要配置 plugins 插件汇合类型是数组
- 每一个插件都是通过 new 来调用,例:new HtmlWebpackPlugin()
- 能够运行 npm run dev/npm run build 查看后果
- 装完插件后运行 webpack 会主动引入咱们作为入口的 index.js
{ * template:'./src/index.html',//应用哪里的html做模板 * filename:'index.html', //编译后的文件名 hash:true,//加hash值 minify:{ //压缩配置 removeAttributeQuotes:true, //去除双引号 collapseWhitespace: true, //折叠去除空格 }}
解决款式 在 webpack 外面所有皆模块
src
- index.html 是模板 不倡议在外面引入货色
- index.js
- style.css
- . index.js 通过 require require('/style.css') 报错如下
You may need an appropriate loader to handle this file typeappropriate 适合的你可能须要一个适合的loader在webpack会把js,css,图片都看成模块,每一个模块都须要对应的模块解析器
- . 配置 module,配置 rules 数组,示意很多规定,用正在匹配 js、css 等,rules 外面配置不容的 loader,每个 loader 的配置都是一个对象
module:{ rules:[]}
loader 的配置办法 test 匹配规定 use 应用什么 loader
yarn add css-loader style-loader -D||
npm install css-loader style-loader -D
- test 示意什么文件应用以后的 loader 用正则配置
- use 的用法
- 字符串 只能写一个 loader
use:'css-loader' - 数组 能够写多个 loader 数组外面能够放字符串和对象
css-loader 解析 require/import 语法
style-loader 把 css 插入到 style 标签中
use:['style-loader','css-loader']use:[{loader:'style-loader'},'css-loader']
loader 的执行程序是从右到左执行 从下到上
rules:[ { test:'/\.css$/',//匹配以css结尾的文件 use:[] }]
- .use 能够间接写 loader,也能够写成对象,写对象的时候能够进行配置
options 能够做一些自定义的配置
{ loader:'style-loader', options:{ insertAt:'top' //css 搁置地位能够决定css的优先级 }
src
- index.js
- b.less
- a.css
public
- index.html
- 配置 less 编译(less->css) 因为从右向左,从下到上执行 所以写在下边和左边
npm install less less-loader -D - 编译 sass
npm install node-sass sass-loader -D - 编译 stylus
stylus stylus-loader -D
{ test:/\.less$/, use:[ 'style-loader', 'css-loader', 'less-loader' ] }
loader的执行程序
- 从下到上 从右到左
抽离 css
- [x] npm install mini-css-extract-plugin -D
- MiniCssExtractPlugin 插件自带一个 loader
- MiniCssExtractPlugin.loader 会主动把 css 抽离进去 作为援用的形式引入页面
new MiniCssExtractPlugin({ filename: 'main.css' ##抽离进去的css的文件名 })
- [x] 在 loader 外面的写法
use: [MiniCssExtractPlugin.loader, "css-loader"]
应用 postcss-loader,autoprefixer 增加浏览器前缀
- [x] yarn add postcss-loader autoprefixer -D
- autoprefixer 主动增加浏览器前缀的插件
- 装置 postcss 插件
yarn add postcss-preset-env -D 容许应用 css 将来个性的插件
- [x] 须要配置 postcss 默认文件 名字
在根目录下创立 postcss.config.js/.postcssrc.js
postcss.config.js/容许你应用将来的 CSS 个性。const postcssPresetEnv = require('postcss-preset-env');// 主动增加浏览器前缀const autoprefixer = require('autoprefixer');module.exports = { plugins: [ postcssPresetEnv, autoprefixer({}) ] };
- 在应用 autoprefixer 做兼容性前缀时,咱们要指定浏览器版本来确定在指定版本中增加兼容性前缀。能够在 package.json 中的 browserslist 字段中指定。或者独自建设一个.browserslistrc 文件
{ test:/\.less$/, use:[ MiniCssExtractPlugin.loader, 'css.loader', 'less-loader', 'postcss-loader' ]}
- 放到所有 cssloader 前面,执行程序起因
npm run dev 的时候会报错 Error: No PostCSS Config found in: /Users/ruanye/Desktop/project/src 没有找到postcss的默认文件
- [x] postcss.config.js 文件外面的内容:
module.exports={ plugins:[require('autoprefixer')] }
解决 js es6 转化成 es5 (babel)
- [x] yarn add babel-loader @babel/core @babel/preset-env
@babel/core babel 外围模块
@babel-preset-env 规范语法转化成低级语法
- presets 预设插件 比方定案的 promise 是不会被转化的
- yarn add @babel/polyfill 曾经废除
{ "presets": [ [ "@babel/preset-env", { "useBuiltIns": "entry" 主动注入依赖 } ] ]}
- useBuiltIns 须要依赖 core-js
- npm install --save core-js@2
- [x] yarn add @babel/plugin-transform-runtime @babel/runtime
- @babel/plugin-transform-runtime 是依赖于 @babel/runtime 的
- @babel/runtime 是生产环境也须要的下载的时候不要加-D
- 作用 @babel/plugin-transform-runtime 去除反复代码
第二种写法
@babel/plugin-transform-runtime 去注入 core-js
须要下载 yarn add @babel/runtime-corejs2
在runtime插件里配置core-js的益处 创立一个沙箱坏境(洁净的坏境,代码不受内部的任何影响)
配置须要解析和不须要解析 loader 的文件门路
- [x] include 蕴含 include:path.resolve(__dirname,'src'),
- [x] exclude 不蕴含 exclude:/node_modules/
{ test:/\.js$/, use:'babel-loader', include:path.resolve(__dirname,'src'), exclude:/node_modules/ 不去匹配node_moudle上面的文件 }
babel 也能够独立进行配置,文件名字.babelrc
- 配置的时候 loader 间接写成 use:'babel-loader',其余配置写在.babelrc 外面
{ presets:['@babel/preset-env'], plugins:[ .... ] }
- 如果 webpack options 对 babel-loader 进行了配置 不须要.babelrc 文件 如果有的就删除
js 语法校验
- yarn add eslint eslint-loader -D
- 初始化 eslint 配置文件
npx eslint --init
- [x] 增加 enforce pre 强制先执行 previous 前置 loader
{ enforce:'pre', test:'/\.js$/', loader:'eslint-loader',}
desServer 下配置项 有报错的时候呈现通明的遮罩层,个别不配置
desServer{overlay: true,...}
* 配置优化项
- yarn add optimize-css-assets-webpack-plugin terser-webpack-plugin -D
optimize: 优化 assets:资源
optimize-css-assets-webpack-plugin 压缩 css 的
terser-webpack-plugin 压缩 js 的 uglify 不反对 es6
optimization: { 优化 minimizer: [ new OptimizeCssAssetsWebpackPlugin({}), new TerserWebpackPlugin({}) ] }
- mode 改成 production
- npm run build 打包之后 csss 是压缩过的
第三方模块的应用
- yarn add jquery
- yarn add expose-loader -D
- expose-loader 负责把变量裸露给全局 loader
- 内联 loader 的形式配置 根本不应用
import $ from "expose-loader?$!jquery"
- 失常 loader 配置
{ test:require.resolve('jquery'), loader:"expose-loader?$"}
- 通过 webpack 提供的内置插件
- 在 plugins 配置,ProvidePlugin webpack 自带插件
- 自带插件都须要引入 webpcak 模块
- 在每个模块中注入$对象 不须要引入能够间接应用$这里 window.$是 undefined;
let webpack = require('webpack')... new webpack.ProvidePlugin({ $:"jquery" })
配置疏忽打包项(次要是引入 cdn 资源的时候)
105 KiB 18.2 KiB
externals:{ jquery:"jQuery"}
通过插件引入 cdn 资源(web 前端优化的一种伎俩)
yarn add add-asset-html-cdn-webpack-plugin
new AddAssetHtmlCdnWebpackPlugin(true, { jquery: 'https://cdn.bootcss.com/jquery/3.4.1/jquery.js', vue: '//cdn.bootcss.com/vue/2.5.16/vue.min.js', vueRouter: '//cdn.bootcss.com/vue-router/3.0.1/vue-router.min.js', }),
在 webpack 中引入图片的几种形式
src
- index.js
- style.css
- b.less
- index.html
- logo.png
- 在 js 中创立图片来引入
import logo from './logo.png'; let img = new Image() ; img.src = logo document.body.appengChild(img)
会在内存外面创立一个新的图片
You may need an appropriate loader to handle this file type你须要一个适合的loader去解决这个文件类型
- 在 css 引入 background(url)
- <img src=''/> 须要把图片放到 dist 文件夹
图片解决
yarn add file-loader html-withimg-loader url-loader -D
file-loader
{ test:/\.(png,jpg,gif)$/, use:'file-loader'}
- [x] 在 html 引入图片打包会找不到文件 须要应用 html-withimg-loader 解决打包之后门路不对的问题
{ test:/\.html$/, use:'html-withimg-loader'}
- 小图片转化成 base64 =>前端优化
- [x] 在图片十分小的状况下不心愿走 http 申请,个别状况下不会间接应用 file-loader 通常咱们应用 url-loader
- 在图片小于多少 k 的时候能够做一个限度,用 base64 来转化,base64 大小会比原来文件大 3 分之 1
- 1024b = 1kb 1024kb = 1m 1g = 1024m
- limit 限度图片大小多大以内 转成 base64
{ test:/\.(png,jpg,gif)\$/, user:{ loder:'url-loader', options:{ limit:10000 示意多少字节 1024 字节是 1kb } } }
- url-loader 能够解决 mp4|webm|ogg|mp3|wav|flac|aac
- url-loder 能够解决各种字体格局 woff2?|eot|ttf|otf
- file-loader 字体话个别倡议用 file-loader,字体转 64 可能存在无奈辨认 file-loader 就是简略的复制粘贴
{ test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, loader: 'url-loader', options: { limit: 0, } }, { test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, loader: 'url-loader', options: { limit: 0 } }
* 打包文件分类
- 图片 loader 的 options 外面增加
options:{ limit:1000 outputPath:'/img/', }
- css 增加在 css 插件外面
new MiniCssExtractPlugin({ filename:'css/main.css' })
- js 增加到 filename 后面
filename:'js/main[hash].js',
- 增加域名 publicPath 的用法
output: { filename: 'bundle.js', path: path.resolve(\_\_dirname, 'build'), publicPath:'http://www.baidu.cn' }
- 如果只须要图片增加域名
options:{ limit:1, outputPath:'/img/', publicPath:'http://www.baidu.cn' }
webpack 配置篇
webpcak 罕用插件
yarn add clean-webpack-plugin -D
革除缓存插件,能够写字符串 也能够写成数组
new CleanWebpackPlugin();- 每次主动删除 dist 目录下的所有文件
- yarn add copy-webpack-plugin -D
拷贝插件
new CopyWebpackPlugin([ //
{from:'img',to:'./'}
]), - 版权插件 webpack 自带插件
let webpack = require('webpack')
new webpack.BannerPlugin('make 2019 by ry')
打包多页利用
- 入口须要配置成对象
entry:{ home:'./src/index.js' other:'./src/other.js' }
- 进口须要多个进口,扭转 filename 的写法
filename:'[name.js]' - 保障 html 页面引入本人对应的 js
应用 chunks 代码块 来实现
chunks:['home']
如果 home 兴许应用 other
chunks:['home','other']
let pages = [{ filename:'index.html', chunk:'index'},{ filename:'login.html', chunk:'login'}].map((item)=>{ // webpack splitChunks 能够配置公共文件的 return new HtmlWebpackPlugin({ // 配置输入的html格局 filename:item.filename, title:'hello', minify:{ removeAttributeQuotesd:true, collapseWhitespace:true, }, chunks:[item.chunk], // 设置援用的代码块 hash:true, // ? 前面的名字 template:'./public/index.html' })})
配置 soure-map 源码映射
文档地址 :https://webpack.docschina.org...
devtool:'source-map'
- source-map 会独自生成一个 sourcemap 文件 能够帮咱们调试源代码 会显示以后报错的列和行
- eval-source-map 不会产生独自的文件 然而会显示报错的行和列
- cheap-module-source-map 不会产生列 然而是一个独自的文件
- cheap-module-eval-source-map 不会产生文件也不会产生列 会间接集成在文件里
实时编译
watch:true
- 监控的选项
watchOptions:{ poll:1000 //每秒问我多少次 aggreatmentTimeout:500 //防抖 始终输出代码 ignored:/node_modules/}
配置环境变量
node 提供的环境变量:process.env.NODE_ENV
依据 wepack 配置的 mode 值
new webpack.DefinePlugin({ // 字符串必须要包两层 'production':JSON.stringify('production'), }),
webpack 解决 跨域问题
- webpack 自带 express
- *代理的形式 重写的形式 把申请代理到 express 服务器上
- target 拜访http://localhost:3000 等于拜访 以后服务器上面 '/api'
- pathRewrite 重写门路 /api/user 等于拜访 localhost:3000/user
devServer:{ ... proxy:{ // '/api':{ target:'http://localhost:3000', pathRewrite:{'/api':''} }// 配置了一个代理 }}
- 间接应用 webpack 提供 mock 数据 webpack 自带 express
- webpack 提供一个办法 before
- 参数是 app app 就是 let app= express()
before(app){ app.get('/user',(req,res)=>{ res.json({name:'leilei'}) }) }
- 能够间接在 node 的服务端启动 webpack 端口是服务端端口 不在须要 npm run dev 来启动 webpack
- yarn add webpack-dev-middleware -D
server.js 批改如下
let webpack = require('webpack');let middle = require('webpack-dev-middleware');let config = require('./webpack.config.js');let compiler = webpack(config);app.use(middle(compiler));
resolve 用法
extensions 拓展名
alias:别名 bootstrap:'bootstrap/dist/css/bootstrap.css'
mainFields 能够配置先找哪个入口
mainFiles:入口文件的名字
resolve:{ modules:[path.resolve('node_modules')], extensions:['.js','.css','.json','.vue'], mainFields:['style','main'] mainFiles:[], // 入口文件的名字 index.js alias:{ bootstrap:'bootstrap/dist/css/bootstrap.css' } }
辨别环境
webpack.config.js 改成 webpack.base.js
新建文件 webpack.prod.js 和 webpack.dev.js
- 配置开发环境的写法
webpack.dev.jslet {smart} = require('webpack-merge');let base = require('./webpack.base.js');module.exports = smart(base,{ mode: 'development', devServer:{ }, devtool:'source-map'})
- 配置生产环境的写法
let {smart} = require('webpack-merge');let base = require('./webpack.base.js');module.exports = smart(base,{ mode: 'production', optimization:{ minimizer:[ ] }, plugins:[]})
最新配置计划
package.json配置
scripts": {"dev":"webpack-dev-server --env.development --config ./build/webpack.config.js","build": "webpack --env.production --config ./build/webpack.config.js"}
let merge = require('webpack-merge');module.exports = (env) => { console.log(process.env.xxx); // 能够通过cross-env 来设置环境变量 if(env.production){ // 生产环境 return merge(base,prod); }else{ return merge(base,dev); }}
webpack 优化
- 自带优化 tree-shaking(树的摇摆),主动去除没有应用的代码,反对生产模式失效
package.json 配置副作用(只对 es6 语法有成果)
- sideEffects:false 副作用的文件不打包
- 要应用哪些副作用
"sideEffects": [
"*.css"
] - 能够用 require ('./style.css')来解决副作用不失效的问题
optimization:{
usedExports:true // 在开发中能够看到哪个包/办法被应用了,其余的没用的会标示
},
- 自带优化 scope-hosting 作用域晋升
let a = 1;let b= 2;let c = a+b;console.log(c);
把变量进行压缩,去提取模块中的导出的变量
- noparse
module: { noParse: /jquery/, // 不去解析 jquery 中的依赖库 ... }
懒加载 import() es6 草案中的语法
yarn add @babel/plugin-syntax-dynamic-import -Dsrc
- index.js
- a.js
- a.js 内容
export default 1234;export const b = 3;
- index.js 内容
let btn = document.createElement('button');btn.innerHTML = '点击实现异步加载';btn.addEventListener('click', async function() { //返回的是一个promise jsonp原理实现的 let res = await import('./a'); console.log(res);});document.body.appendChild(btn);
- 热更新(浏览器强制刷新叫做硬更新),热更新就是代码批改之后浏览器不须要刷新 css-loader 自身反对热更新
- devServer 配置
devServer:{ hot:true}
- plugins 外面配置热更新插件
new webpack.HotModuleReplacementPlugin()
- 代码外面的写法热更新文件夹外面
- IgnorePlugin 疏忽 webpack 内置插件 以 mement 库为例 间接应用会引入所有的语言包 配置疏忽项之后咱们只须要手动引入咱们须要的语言包 打包的时候只打包须要的
- 配置疏忽项之前打包大小 287kb 配置疏忽项之后打包的大小 - 67.8k
- index.js 内容
import moment from 'moment'; 设置语言 手动引入所须要的语言 import 'moment/locale/zh-cn' moment.locale('zh-cn'); let r = moment().endOf('day').fromNow(); console.log(r);
- 插件写法
new webpack.IgnorePlugin(/\.\/locale/, /moment/)
- happypack 能够应用多线程来打包
yarn add happypack
- id 通知 happy 打包的时候用哪个 id 对应哪个 loader 进行多线程打包
- js 多线程打包 扭转 babel-loader 的写法
{ test: /\.js$/, ... use: { loader: 'happypack/loader?id=js' } } new Happypack({ id:js, use:'babel-loader', })
- css 也能够实现多线程打包
{ test: /\.css$/, use: 'Happypack/loader?id=css' } new Happypack({ id: 'css', use: ['style-loader', 'css-loader'] })
- 抽离公共代码(多入口)
optimization:{ // commonChunkPlugins splitChunks:{ // 宰割代码块 cacheGroups:{ // 缓存组 common:{ // 公共的模块 chunks:'initial', minSize:0, minChunks:2, }, vendor:{ //第三方模块 priority:1, //权重 test:/node_modules/, // 把你抽离进去 chunks: 'initial', minSize: 0, minChunks: 2 } } } }
wepack 框架配置 vue 的应用
- 应用 vue 模板须要写 template
yarn add vue vue-loader vue-template-compiler - vue-loader 解析 vue 文件
- vue-template-compiler 解析 vue 中的 template
- 配置扩展名和别名
- https://cn.vuejs.org/v2/guide/installation.html#%E5%AF%B9%E4%B8%8D%E5%90%8C%E6%9E%84%E5%BB%BA%E7%89%88%E6%9C%AC%E7%9A%84%E8%A7%A3%E9%87%8A resolve:{ extensions: ['.js','.vue','.json'], alias: { //开发环境应用 vue.esm.js 'vue\$': 'vue/dist/vue.esm.js', // 退出这句话 } },
- vue-loader 须要应用 vueLoaderPlugin 插件
const VueLoaderPlugin = require('vue-loader/lib/plugin') plugins: [ new VueLoaderPlugin() ] }
- 配置 loader 解析 vue 文件
module.exports = { module: { rules: [ ... { test: /\.vue$/, loader: 'vue-loader' } ] },
VueLoaderPlugin 这个插件的职责是将你定义过的其它规定复制并利用到 .vue 文件里相应语言的块。例如,如果你有一条匹配 /.js$/ 的规定,那么它会利用到 .vue 文件里的 <script> 块。
当初咱们就能够依照 vue 模板的模式来编写代码了。
4.解决vue外面款式的问题 yarn add vue-style-loader
odule.exports = { // other options... module: { rules: [ { test: /\.vue$/, loader: 'vue-loader', options: { loaders: { css: ExtractTextPlugin.extract({ use: 'css-loader', fallback: 'vue-style-loader' // 这是vue-loader的依赖 }) } } } ]
<template> <div class="divWrap"></div></template><script>export default { data(){ return {} }, created(){}, methods:{}}</script><style scoped>.divWrap{}</style>