安装 webpack 和 webpack cli
yarn add webpack webpack-cli -D
创建webpack.config.dev.js
开发版本下的配置文件
const path = require('path')
module.exports={
//模式(development,production)
mode:'development',
//
devtool:'source-map'
//入口文件,如果不配置entry项,则默认在src目录下找index.js,
entry: {
index:'./src/js/index.js',
//detail:'./src/js/detail.js' 如果是多页面情况,则可以直接在entry中写别的页面
},
//将两个文件打包到一个下
//entry:[path.resolve(__dirname,'../app.js'),path.resolve(__dirname,'../component/Heade.js')]
//出口文件,路径不可为相对路径,如果不设置output项,则默认导出到根目录的dist/main.js文件
output:{
//路径
path:path.resolve(__dirname,'./dist'),
//文件名,这里可添加6位哈希后缀
filename:'index-[hash:6].js'
//当配置了多页面的时候,这里就需要起别名了,这里就会根据入口文件名打包成两个文件。
filename:'[name].js'
}
}
文件后缀hash生成是根据文件的内容进行编码的,内容不变化则hash值不变化
打包路径设置
module.export={
...
entry: {
'script/index':path.resolve(__dirname,'./app.js')
//在入口文件名处可以写路径信息,也会添加到相应文件内
},
output: {
//在文件名前面可以添加路径,打包后会放到指定的路径下
filename: 'script/[name]-[hash:6].js'
},
}
安装 HtmlWebpackPlugin
将页面模板页面和js文件进行整合
...
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
...
plugins: [//js与html模板匹配
new HtmlWebpackPlugin({//实例化
title: '没啥意思的小网页',
//设置打开的标签页名称 title,模板页面设置<title><%= htmlWebpackPlugin.options.title %></title>
template: './src/views/index.ejs',
//模板文件路径
//自动存储到 output配置的目录
filename: 'index.html',
//默认为index.html,如果更改可从服务端修改首页名称,
// chunks: ['index']
//指定入口的js文件,仅添加所需的模块,不将其他与本页无关的模块加载进来
}),
]
}
安装 webpack-dev-server
webpack-dev-server
为你提供了一个简单的web服务器,并且能够实时重新加载(live reloading)。文件时保存再内存中的,打开速度更加迅速。
官网:https://www.webpackjs.com/guides/development/#%E4%BD%BF%E7%94%A8-webpack-dev-server
yarn add webpack-dev-server -D
安装后可以在webpack.config.dev.js
中配置 devServer
项,可以设置浏览器打开和端口号
module.exports = {
...
devServer: {
port: 9000,//端口号
open: true,//打开浏览器
contentBase: './dist',//serve运行的根目录
compress:true//是否压缩
}
}
配置完成后需要在package.json
中配置下面这,即可通过 yarn dev
来启动
"dev": "webpack-dev-server --config webpack.config.dev.js"
sass-loader的使用
把浏览器不识别的内容做转换,loader 用于对模块的源代码进行转换。loader 可以使你在 import
或"加载"模块时预处理文件。
创建scss文件:common.scss
$base: blue;
body{
background:$base;
}
在入口文件index.js中引入
import '../style/common.scss'
class Index{
constructor(){
console.log('webpack.js')
}
}
new Index()
在yarn dev 的时候webpack并不会识别scss的文件,这个时候就需要loader来帮助webpack来识别内容并且编译
在引入scss的时候需要安装 node-sass sass-loader
yarn add node-sass sass-loader
在使用sass-loader的时候需要安装另外两个依赖:css-loader,style-loader
module.exports = {
...
module: {
rules: [
{
test: /\.s[ac]ss$/,//选择出需要转换的文件
use: [
//将JS字符串生成为style节点,会在页面生成style样式
'style-loader',
//将css转换为common.js模块
'css-loader',
//把.sass .scss转为.css
'sass-loader'
]
}
]
}
}
这种形式的写法会导致样式文件直接插入到页面的head标签内部的style标签内,有时候我们还需要引入单独的css文件,这时候就需要MiniCssExtractPlugin。
MiniCssExtractPlugin
安装
yarn add mini-css-extract-plugin -D
用法:首先在入口文件引入样式文件,再由该插件独立出来
...
const miniCssExtractPlugin = require(mini-css-extract-plugin)
module.exports = {
...
plugins:[
...
new miniCssExtractPlugin({
filename:'[name]-[hash:6].css'
//设置了css文件名字和入口entry文件名一致,并添加6位哈希
})
],
module: {
rules: [
{
test: /\.s[ac]ss$/,//选择出需要转换的文件
use: [
miniCssExtractPlugin.loader,
//这里不需要渲染为style标签的形势了,所以可以不走style-loader
//'style-loader',
//将css转换为common.js模块
'css-loader',
//把.sass .scss转为.css
'sass-loader'
]
}
]
}
}
因为我们在entry入口处配置了路径:
entry: {
'script/index':path.resolve(__dirname,'./app.js')
},
当我们想要将css文件导报到指定路径下时可以在miniCssExtractPlugin中配置moduleFilename
new miniCssExtractPlugin({
// filename: '[name]-[hash:6].css',
moduleFilename: ({ name }) => `${name.replace('script', 'style')}-[hash:6].css`,
//将原本的script替换为style路径,并为css文件添加hash后缀
})
生产环境的配置
将一些生产条件下不需要的内容去掉,并且在package.json中定义
"build":"webpack --config webpack.config.pro.js"
devTool
module.exports={
...
devtool:'inline-source-map'
//代码调试,可以看到源代码
}
babel 和垫片@babel/polyfill 的使用
babel的初次使用
当我们引入高标准代码后,浏览器可能不识别类似箭头函数,promise,let等语法,这时候就需要babel语法转换器
我们需要使用babel-loader时需要按照的依赖
npm install -D babel-loader @babel/core @babel/preset-env
yarn add babel-loader @babel/core @babel/preset-env --dev
创建一个js文件,并且在入口文件引入import './app.js'
//app.js
const fuc=()=>{
console.log('箭头函数')
}
export default fuc
然后需要在config中配置一下module
module:{
{
test:/\.js$/,
use:{
loader:'babel-loader',
options:{
//插件集合
presets:['@babel/preset-env']
}
}
}
}
通过yarn build 打包后的js文件内就不是原封不动的js,而是编译完成的浏览器可识别的代码
__webpack_require__.r(__webpack_exports__);
var fuc = function fuc() {
console.log('箭头函数');
};
垫片
安装
yarn add @babel/polyfill --dev
方法一:简单粗暴,在入口文件引入,即可将高阶代码转换为低版本的
import @babel/polyfill
这样会把所有的方法载入,文件内容会很大,所以垫片的形式不会按需载入,且会污染全局环境
方法二:在配置文件的entry导入
entry: {
index:['@babel/polyfill',path.resolve(__dirname,'./js/index')]
},
方法三:设置presets
module:{
{
test:/\.js$/,
use:{
loader:'babel-loader',
options:{
//插件集合
"presets": [
[
"@babel/preset-env",
babel 7.3
{
"targets": {//浏览器兼容版本
"chrome": "58",
"ie": "11"
},
"useBuiltIns": "usage"//该配置项下方详解
}
],
"@babel/preset-react"
],
}
}
}
}
useBuiltIns: 参数有 “entry”、”usage”、false 三个值
默认值是false,此参数决定了babel打包时如何处理@babel/polyfilll 语句。
-
“entry”: 会将文件中
import @babel/polyfilll
语句 结合 targets ,转换为一系列引入语句,去掉目标浏览器已支持的 polyfilll 模块,不管代码里有没有用到,只要目标浏览器不支持都会引入对应的 polyfilll 模块。 -
“usage”: 不需要手动在代码里写
import @babel/polyfilll
,打包时会自动根据实际代码的使用情况,结合 targets 引入代码里实际用到部分 polyfilll 模块 -
false: 对 import‘@babel/polyfilll’不作任何处理,也不会自动引入 polyfilll 模块。
需要注意的是在 webpack 打包文件配置的 entry 中引入的 @babel/polyfill 不会根据 useBuiltIns 配置任何转换处理。
除非是不得已不需要通过 import @babel/polyfill
一次将所有的polyfill文件引入
core.js@3
可以用来转化一些高级语法,很多@babel/polyfill的proset-env 做不到的就需要依赖 core.js@3这个包
core-js是我们能够使用新的API的最重要的包,然而一般情况它隐藏在webpack编译后的代码中,我们一般不会去查看,所以容易被遗忘,我们在webpack生成环境下,查看编译后的代码,可以看到例如includes就是从core-js导出到我们的代码去的。
core-js是什么
- 它是JavaScript标准库的polyfill
- 它尽可能的进行模块化,让你能选择你需要的功能
- 它可以不污染全局空间
- 它和babel高度集成,可以对core-js的引入进行最大程度的优化
升级core-js@3动机
目前我们使用的都默认是core-js@2,它在 2018年 之前就封锁了分支,至此之后的特性都只会添加到core-js@3,这里有一个生产例子,使用了core-js@2不支持的新特性,导致错误
- core-js@2出现的问题
- Vue-cli使用flat报错
- vue-cli也会在V4升级core-js
- Roadmap for Vue-cli4
- core-js@3添加的特性
core-js@3 特性概览
- 支持ECMAScript稳定功能,引入core-js@3冻结期间的新功能,比如flat
- 加入到ES2016-ES2019中的提案,现在已经被标记为稳定功能
- 更新了提案的实现,增加了proposals配置项,由于提案阶段不稳定,需要谨慎使用
- 增加了对一些web标准的支持,比如URL 和 URLSearchParams
- 现在支持原型方法,同时不污染原型
- 删除了过时的特性
core-js@3 与 babel
以前我们实现API的时候,会引入整个polyfill,其实polyfill只是包括了以下两个包
core-js
regenerator-runtime //包含promise的包
core-js@3 升级之后弃用了@babel/polyfill,以下是等价实现
首先需要手动安装一下core-js@3
// babel.config.js
presets: [
["@babel/preset-env", {
useBuiltIns: "entry", // or "usage",见如下说明
corejs: "3",
}]
]
// 如果 useBuiltIns: "entry" 需要在打包入口文件导入两个包:
import "core-js/stable"
import "regenerator-runtime/runtime"
// 如果 useBuiltIns: "usage",不需要在入口文件里导入包了
总结
core-js@3 废弃了 babel-polyfill,实现了完全无污染的API转译,非常有潜力,但是其暂时会增加打包体积,这个还得看未来普及度上来之后的权衡
clean-webpack-plugin
安装:
yarn add clean-webpack-plugin --dev
这个插件用于将我们每次build时之前的导出目录进行删除
使用:
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
plugin:[
new CleanWebpackPlugin()
]
postcss-loader
用于给样式添加前缀,类似于根据浏览器内核的命名
安装:
yarn add postcss-loader
安装依赖:
yarn add postcss-preset-env --dev
配置:需要配置到匹配样式的rules下
{
loader: "postcss-loader",
options: {
ident: "postcss",
plugins: () => [require("postcss-preset-env")()]
}
}
url-loader file-loader
用于匹配图片文件的loader
安装:
yarn add url-loader file-loader --dev
{
test: /\.(jpg|jpeg|png|gif)$/,
use: {
loader: 'url-loader',
options: {
limit: 8000000,//如果文件大小超过该大小则不放入指定目录
name: '[name]-[hash:6].[ext]',
outputPath: 'images/'//保存目录
}
}
},
对vue、react框架的引入
react
安装 react 和 react-dom
yarn add react react-dom
在入口文件entry中引入react和react-dom
import React from 'react'
import ReactDom from 'react-dom'
创建一个组件App.jsx,因为webpack目前还不支持识别jsx,我们需要将之前的配置进行改变
{
test: /\.jsx?$/,
//更改文件匹配
use: {
loader: 'babel-loader',
options: {
presets:[
'@babel/preset-env',
'@babel/preset-react'//需要添加这个预设
]
}
}
},
安装 @babel/preset-react
用于解析jsx语法
yarn add @babel/preset-react --dev
在模板文件中的根节点添加id 为 root
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<div id="root"></div>
</body>
</html>
入口文件配置:
import React from 'react'
import ReactDom from 'react-dom'
import App from '../components/App.jsx'
import '../style/common.scss'
ReactDom.render(
<App></App>,
document.querySelector('#root')
)
对vue的引入
这里需要使用到vue-loader
在使用vue-loader的时候需要引入两个包
yarn add vue-loader vue-template-compiler --dev
并且在webpack.config文件中引入,然后在配置文件中添加vue-loader,再添加相应plugin
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
module: {
rules: [
// ... 其它规则
{
test: /\.vue$/,
loader: 'vue-loader'
}
]
},
plugins: [
// 请确保引入这个插件!
new VueLoaderPlugin()
]
}
resolve.extensions
自动解析确定的扩展。
该配置项属于resolve项
alias 别名配置
在config文件中创建resolve项
module.export={
resolve:{
alias: {
'@':path.resolve(__dirname,'./src/components')
}
},
}