webpack默认只认识 js 文件和 json文件, 但是webpack 可以使用 loader 来加载预处理文件, 允许webpack也可以打包 js之外的静态资源。
所以webpack如果要处理其他文件类型, 记得要先配置对应的 loader
没有css-loader的报错演示
require('./css/base.css')
报错图演示:
翻译: 你需要一个合适的loader, 去处理这个文件类型
需求: 去掉小圆点, 清除默认的margin 和 padding, 新建 css 目录
yarn add style-loader css-loader -D
配置
module: {
// loader的规则
rules: [
{
// 正则表达式,用于匹配所有的css文件
test: /\.css$/,
// 先用 css-loader 让webpack能够识别 css 文件的内容
// 再用 style-loader 将样式, 以动态创建style标签的方式添加到页面中去
use: [ "style-loader", "css-loader"]
}
]
},
我们上面的操作,使得css
和js
文件混杂在一起了,将css放到了style标签中, 和html一起加载了一个文件请求次数是少了
但是如果css文件太大的话,也不是太好,那有没有什么办法把css
分离出来呢?
https://webpack.docschina.org/
有一个插件,mini-css-extract-plugin
,这个插件支持webpack4.x
还有一个插件extract-text-webpack-plugin
这个插件对webpack3.x
的版本支持,被webpack4.x
废弃了 (所以没用了)
安装依赖包
yarn add mini-css-extract-plugin -D
在webpack.config.js
文件中,引入这个模块
// 引入分离 css 文件的 模块
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
配置loaders
// 模块加载
module: {
// loader的规则
rules: [
// 配置 css 文件的解析
{
test: /\.css$/,
use: [ // 根据官方文档写的,注意'css-loader'的书写位置
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath:'../',
},
},
'css-loader'
]
},
],
}
插件的配置 (不要忘了这步)
plugins: [
new HtmlWebpackPlugin({
template: './public/index.html' }),
// 定义打包好的文件的存放路径和文件名
new MiniCssExtractPlugin({
filename:'css/index.css'
})
],
下载依赖包
注意: 解析less文件需要识别 less 语法, 所以除了 less-loader
需要额外下载 less
包
less-loader: 将less转换成 css
yarn add less less-loader -D
配置
// 配置 less 文件的解析
{
test: /\.less$/,
use: [
// 分离出 css 内容
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath:'../',
},
},
'css-loader',
'less-loader'
]
}
我们试了一下,在css
中用到一下背景图片,结果就报错了,难道webpack
连图片也认不出来吗?
没有错,的确认不出来, 此时需要转换图片的 loader, 来处理图片的问题, 主要用到 url-loader
和 file-loader
注意: url-loader
中的部分功能要用到 file-loader
, 要下载两个模块
下载依赖包
yarn add url-loader file-loader -D
配置loader
{
test: /\.(png|jpg|gif)$/i,
use: [
{
loader: 'url-loader' }
]
}
图片默认转成 base64 字符串了,
base64
就会让图片的体积增大 30% 左右, 得不偿失所以需要通过 options 配置选项进行配置 limit, 可以设置一个临界值, 大于这个值会整个文件直接打包到目录中, 得到是路径,
如果小于这个值, 就会转成 base64, 节约请求的次数
{
test: /\.(png|jpg|gif)$/i,
use: [
{
loader: 'url-loader',
options: {
// 超过 8k 就不转 base64, 小于 8k 才转
limit: 8 * 1024
}
}
]
}
默认是直接输出到了 dist 根目录, 可以通过 options 进行配置
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
// 超过 8k 就不转 base64, 小于 8k 才转字符串
limit: 8 * 1024,
// 配置输出的文件名
name: '[name].[ext]',
// 配置静态资源的引用路径
publicPath: "../images/",
// 配置输出的文件目录
outputPath: "images/"
}
}
]
}
之前有问题: 打包出新的内容时, 之前的内容, 还残留!!!
使用 clean-webpack-plugin插件 在每次打包前清除下dist文件夹。
安装依赖包
yarn add clean-webpack-plugin -D
webpack.config.js
// 其他代码
// 导入清除插件
const {
CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
// 其他配置
plugins: [
// ....
// 调用清除打包目录插件
new CleanWebpackPlugin()
]
}
字体图标 和 图片的配置一致
// 处理字体图标的解析
{
test: /\.(eot|svg|ttf|woff|woff2)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 8 * 1024,
// 配置输出的文件名
name: '[name].[ext]',
// 配置静态资源的引用路径
publicPath: "../fonts/",
// 配置输出的文件目录
outputPath: "fonts/"
}
}
]
}
babel 的介绍 => 用于处理高版本 js语法 的兼容性
1. 安装包
yarn add -D babel-loader @babel/core @babel/preset-env
2. 配置规则
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
]
}
webpack可以实现,保存时(ctrl + S),可以自动刷新浏览器(内存中打包后刷新浏览器)
webpack-dev-server自动刷新这个工具,可以起一个开发服务器,可以实时保存就刷新页面(打包到内存中,不会写入到dist目录生成文件)
yarn add webpack-dev-server -D
"scripts": {
"build": "webpack --config webpack.config.js",
"dev": "webpack-dev-server --config webpack.config.js"
}
yarn dev
// 或者
npm run dev
注意:
yarn dev: 开发过程中用, 起一个开发服务器, 打包在内存中, 可以保存时实时刷新
yarn build: 上线前用, 代码写完了, 执行yarn build生成打包后的文件, 上传到站点服务器, 供用户访问即可
module.exports = {
...,
// 配置开发服务器
devServer: {
port: 3000, // 可以更改端口号
open: true // 自动打开浏览器
}
}
生产环境和开发环境刚好相反,开发环境在本地运行,而生产环境是要产出运行在服务器 给用户使用的代码
,因此两者的构建目标差异很大,比如打包后的文件在生产环境中要尽可能的小,逻辑代码分离,优化静态资源(压缩图片)等。
因此开发环境和生产环境不能共用一份webpack配置文件,需要分别指定
但是两个环境还是有很多配置可以共用的,比如entry、output、module等,因此可以把公共部分的配置抽离出来放到一个独立的文件然后进行合并,我们可以使用webpack-merge
工具来进行合并。
注意: entry、output、module这些配置在我们当前示例通用,但未必适合所有项目。
安装依赖
yarn add webpack-merge -D
使用介绍
// 用于合并webpack配置的插件
const {
merge } = require('webpack-merge')
const obj = merge({
a: '1' }, {
b: '2', c: '3', a: '4' } )
// { a: '4', b: '2', c: '3' }
开始拆分webpack.config.js
文件,拆分后这个文件就不要了。
新建config
文件夹:
- webpack-demo
- config // 存放配置文件的文件夹
- webpack.base.js // 公共的配置
- webpack.dev.js // 开发环境的配置(代码不要压缩,可以查看源代码)
- webpack.pro.js // 生产环境的配置(上线的环境,压缩过的)
- // 其他文件
配置文件
config/webpack.base.js
// 存放公共的部分
const path = require('path')
// 引入自动生成 html 的插件
const HtmlWebpackPlugin = require('html-webpack-plugin')
// 引入分离 css 文件的 模块
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
// 导入清除插件, 可以在每次打包之前, 清除 dist目录的内容
const {
CleanWebpackPlugin } = require('clean-webpack-plugin')
// 配置webpack的配置文件, 需要将配置的对象导出, 给webpack使用
module.exports = {
// 入口 entry, 从哪个文件开始打包
entry: './src/main.js',
// 出口 output, 打包到哪里去
output: {
// 打包输出的目录 (输出的目录必须是一个绝对路径)
path: path.join(__dirname, '../dist'),
// 打包后生成的文件名
filename: 'js/bundle.js'
},
// 配置module模块加载规则
// 默认, webpack只认识json, javascript, 不认识其他文件, 如果希望打包处理其他文件, 需要配置对应loader
module: {
rules: [
...
]
},
// 配置插件
plugins: [
...
]
}
webpack.dev.js
// 存放开发模式下的配置 development
const base = require('./webpack.base.js')
// 用于合并webpack配置的插件
const {
merge } = require('webpack-merge')
// merge 可以接受多个参数, 把参数对象合并成一个对象
// 后面的对象属性, 会覆盖前面的对象属性
module.exports = merge(base, {
// 这里写你的额外的dev的配置
// 配置开发服务器
devServer: {
port: 3000, // 端口号
open: true // 自动打开浏览器
},
// mode:模式
mode: 'development' // 不需要导出
})
webpack.pro.js
// 存放生产模式的配置 production
const base = require('./webpack.base.js')
// 用于合并webpack配置的插件
const {
merge } = require('webpack-merge')
// merge 可以接受多个参数, 把参数对象合并成一个对象
// 后面的对象属性, 会覆盖前面的对象属性
module.exports = merge(base, {
mode: 'production' // 声明当前是生产环境
})
注意: 拆分完
webpack.config.js
后可以把该文件删除了。
修改scripts
启动命令,注意指定配置文件的路径变化
package.json
{
"scripts": {
"build": "webpack --config config/webpack.pro.js",
"dev": "webpack-dev-server --config config/webpack.dev.js"
},
}
易错点:
打包后的输出路径需要修改
// 打包输出的目录 (输出的目录必须是一个绝对路径)
path: path.join(__dirname, '../dist'),
修改scripts启动命令, 注意指定配置文件的路径变化
"build": "webpack --config config/webpack.pro.js",
"dev": "webpack-dev-server --config config/webpack.dev.js"
improt export(浏览器和node都不支持),新语法必须被webpack解析处理才能运行
在之前的 javascript 中一直是没有模块系统的,前辈们为了解决这些问题,提出了各种规范, 最主要的有CommonJS和AMD两种。前者用于服务器,后者用于浏览器。而 ES6 中提供了简单的模块系统,完全可以取代现有的CommonJS和AMD规范,成为浏览器和服务器通用的模块解决方案。
CommonJS: node服务器端 const fs=require(‘fs’) module.exports={ … }
AMD:浏览器 requirejs(淘汰)
CMD:浏览器 seajs(淘汰)
标准化模块化语法=>es6模块化语法,通用的模块化解决方案=>import导入 export导出
一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果你希望外部能够读取模块内部的某个 变量,就必须使用export关键字输出该变量。下面是一个JS文件,里面使用export命令输出变量。
es6 中新增了两个命令 export
和 import
, export
命令用于规定模块的对外接口,import
命令用于输入其他模块提供的功能
// a.js
export const name = 'pp'
export const age = 18
export const desc = '很帅'
使用export命令定义了模块的对外接口以后,其他JS文件就可以通过import命令加载这个模块(文件)
//main.js
import {
name, age, desc} from './a.js'
console.log('从模块内部导出的内容:', name, age, desc)
上面介绍了模块化最基础的用法,export 不止可以导出函数,还可以导出对象,数组,字符串等等
//a.js
export const name = 'pp'
export const arr = [1, 2, 3]
export const obj = {
name: 'zs',
age: 18
}
export的写法,除了像上面这样,还有另外一种。
//a.js
const name = 'pp'
const arr = [1, 2, 3]
const obj = {
name: 'zs',
age: 18
}
// 优点:上面代码在export命令后面,使用大括号指定所要输出的一组变量。它与前一种写法是等价的,但是应该优先考虑使用这种写法。因为这样就可以在脚本尾部,一眼看清楚输出了哪些变量。
export {
name, arr, obj}
---------------------------------
import {
obj } from '模块'
export default
指定默认输出, 只能导出一个值, import 无需知道变量名就可以直接使用
//a.js
export default function fn () {
console.log('哈哈')
}
//main.js
//在导入时,可以随意的使用变量名来接收
import a from './a'
a()
注意:export default是非常用的语法,用的很多, 以一些常用的模块为例
import $ from 'jQuery' // 加载jQuery 库
import moment from 'moment' // 加载 moment
import
为加载模块的命令,基础使用方式和之前一样
//main.js
import {
name, arr, user} from './a'
//如果是export default导出的内容
import a from './a'
上面介绍了,es6 中模块的使用方式,但是现在es6的模块化,无论在浏览器端还是 node.js 上都没有得到很好的支持,所以需要,一些转码的工具(babel)。使我们可以用es6的方式来编码,最后输出es5的代码。