初识打包工具
grunt/gulp
区别:
-
gulp的核心是task
-
我们可以配合一系列的task,并且定义task要处理的事务(例如ES6、ts转换,图片压缩,scss转成css),之后让grunt/gulp来一次执行这些task,而且让整个流程自动化,所以grunt/gulp也被称为全段自动任务管理工具
-
task就是将src 下面的所有js文件转成ES5的语法,并且最终输出到dist文件夹中.
什么时候使用grunt/gulp呢?
- 如果你得工程模块依赖非常简单,甚至是没有用到模块化的概念。
- 只需要进行简单的合并、压缩,就使用grunt/gulp即可。
- 但如果整个项目使用了模块化管理,而且相互依赖非常强,我们就可以使用更加强大的webpack了
所以,grunt/gulp和webpack有什么不同呢?
grunt/gulp 更加强调的是前端流程的自动化,模块化不是它的核心
webpack更加强调模块化开发管理,而文件压缩合并、预处理等功能,是它附带的功能
配置安装
全局安装:
npm install webpack --save-dev -g
npm install webpack webpack-cli --save-dev
在使用的时候需要进行本地安装:(必须)
npm install webpack --save-dev
npm install webpack-cli --save-dev
或 npm i webpack webpack-cli -D
指定版本安装:
npm install [email protected] -g
查看版本号:
webpack --version
全局webpack和局部webpack
1、在全局安装一个webpack之后,在本地再安装一个webpack避免版本不兼容导致编译错误
npm install [email protected] --save-dev
2.再次打开package.json文件
"devDependencies": {
"webpack": "^3.6.0"
}
3.如果在package.json文件添加"build": "webpack"则优先执行本地的webpack
安装报错处理:
刚开始默认装的webpack4.41.5的,webpack时报错,按照提示也无法解决
于是换了版本,先卸载
npm uninstall webpack -g
在安装指定版本 ,我装的是3.5.5
npm install [email protected] -g
但是上面指令依然报错:
解决办法,将安装指令换为:npm install [email protected] -g --unsafe-perm
成功解决问题。
目录结构
myapp
|__dist
| |__styles
| |__js
| |__bundle.js
| |__index.html
|__src
| |__component
| |__index.js
|__node_modules
|__package.json
|__webpack.config.js
1、npm init -Y 生成package.json文件和node_model文件夹
package.json文件主要用于webpack处理指令的定义和外部插件的引入
详解package.json中命令:
webpack-dev-server //启动webpack-dev-server
--progress --colors //打包进行显示颜色
--hot //开启模块热修复功能
--content-base ./dist //设置webpack-dev-server运行的根目录是 ./dist
--inline //使用inline的方式进行页面自动刷新
--quiet //控制台中不输出打包信息
--compress //开启gzip压缩
node_model文件夹用于存储所有的工具模块
2、创建src和dist文件夹
src文件夹用于保存静态资源——打包前的文件
dist文件夹用于保存打包后的文件
3、创建webpack.config.js文件
webpack.config.js 文件用于统一配置webpack功能模块
包含:
const {resolve} = require('path') // 使用node的绝对路径模块
// 或 const path = require('path') // 使用node的绝对路径模块path.resolve
const HtmlWebPlugin = require('html-webpack-plugin') // 引入处理HTML文件的插件
module.exports = {
// entry: resolve(__dirname + "./src/main.js")
// entry: ["./src/main.js","./src/index.js"] // 多文件入口文件 数组形式
entry: {
main: "./src/main.js",
index: "./src/index.js"
}, // 多文件入口文件对象形式
output: { // 文件打包后输出口
path: resolve(__dirname + "/dist"), //打包后的文件存放的地方
filename: "[name]-[hash].js" // 打包后输出文件的文件名
// filename: "name.js" // 单文件输入出
},
module: { // 安装loader
rules: [
{
test: /\.css$/, // 正则匹配以.css结尾的文件
use: ['style-loader', 'css-loader'] // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的
},
{
test: /\.less$/, // 正则匹配以.css结尾的文件
use: ['style-loader', 'css-loader', 'less-loader'] // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的
}
]
},
plugins: [ // 插件管理
new HtmlWebPlugin({ // HTML文件处理插件
template: './src/index.html'
})
],
resolve: { //其他解决方案配置
extensions: ['', '.js', '.json', '.css', '.scss']//添加在此的后缀所对应的文件可以省略后缀
},
devServer: { //设置本地服务的端口号,不设置则默认为8080端口
contentBase: "./dist", // 本地服务器所加载文件的目录
port: "8088", // 设置端口号为8088
inline: true, // 文件修改后实时刷新
historyApiFallback: true, //不跳转
},
mode: 'development' // development开发环境、production生产环境
}
打包指令及相关配置
执行方式一:
webpack4.0之前的执行方式
webpack .\src\main.js -o .\dist\bundle.js
需要打包的js 兼容 生成的新的js
webpack4.0之后的执行方式
webpack src/index.js --output dist/bundle.js
执行方式二:通过webpack命令执行打包
// 1. 创建webpack.config.js文件
const path = require('path')
module.exports = {
entry: './src/main.js', // 入口路径
output: { // 出口路径
path: path.resolve(__dirname, 'dist'), // 动态获取路径
filename: 'bundle.js',
publicPath: 'dist/' // 如果出现url引用资源自动更改路径
}
}
// 2. npm init // 初始化生成page.json文件
// 3. npm install // 加载npm包依赖
执行方式三:在执行方式二的基础上配置package.json文件
package.json文件添加"build": "webpack"之后可以执行npm run build来打包
"scripts": {
"buid": "webpack" // build指令可以自定义,如果是start则比较特殊,运行的时候不需要run指令:npm start
}
解决webpack因新版本打包失败问题--ERROR in multi ./src/main.js ./dist/bundle.js
最近在学习webpack打包过程中遇到的一个问题向大家分享下!
创建了一个webpacksty的目录,目录下放着dist,src子目录,然后通过node环境下,npm init -y
初始化项目出现package.json文件,src子目录下又存放着index.html和main.js文件,接下来尝试着在main.js输入一句代码当验证打包后续是否成功的过程:
console.log("ok");
接下就是执行webpack打包命令了
把src下的main.js打包到dist下的bundle.js,执行命令:
webpack .\src\main.js .\dist\bundle.js
执行后:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J32qn4Fq-1648807954349)(/Web/Notes/images/webpack1.png)]
报错了!此时也可以直接看出我的webpack版本号:4.30.0 ,算是新版本了。
当然此时查看结构目录下dist肯定没有bundle.js的文件出现,然后自己也是看别人的博客查询到了原来是版本过高,以前的命令已经不适用了,只要加-o就轻松解决原来。
webpack .\src\main.js -o .\dist\bundle.js
此时就执行成功了!
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TSGDTP5C-1648807954350)(/Web/Notes/images/webpack2.png)]
在dist目录下也自动生成了bundle.js的文件。
常用的loader
样式处理:
// css-loader负责将css文件进行加载
npm install css-loader --save-dev
// style-loader负责将样式添加到DOM中
npm install style-loader --save-dev
npm i sass-loader node-sass --save-dev
*node-sass最近几个版本安装可能会报错,我今天就遇到,github也有网友反映了这问题(见上篇)
*使用sass要先安装ruby,然后命令行gem sass (这不影响我们在项目的webpack中使用sass)
npm install less-loader --save-dev
// 解决CSS3兼容性
npm i postcss-loader autoprefixer --save-dev
npm i postcss postcss-loader postcss-preset-env -D
ES6处理:
npm install --save-dev babel-loader babel-core
npm install babel-preset-env --save-dev
或者制定版本号
npm install --save-dev babel-loader@7 babel-core babel-preset-es2015
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015']
}
}
}
]
}
当用到promise、map、或者ES6数组方法的时候
babel 默认只转换新的 JavaScript 语法,
不转换新的API以及一些定义在全局对象上的方法,
如果想使用这些新的对象和方法,则需要为当前环境提供一个垫片polyfill
第一步:
npm install --save babel-polyfill
第二步:创建.babelrc文件
{
"presets": ["env"]
}
第三步:
babel-polyfill用正确的姿势安装之后,引用方式有三种:
require("babel-polyfill");
import "babel-polyfill";
module.exports = {
entry: ["babel-polyfill", "./app/js"]
};
文件处理:
然后是文件方面的,帮我们处理图片等:
npm i file-loader url-loader --save-dev
在webpack上处理图片的时候,难免会因为路径问题困惑。
我们知道项目中引用图片有以下几种情景:
- html的
<img src=' ' >
- css中背景图片引用
- js中动态创建/生成img
- 行内样式中设置background-image
在webpack使用file-loader对图片打包时:
- 用html-withimg-loader配合htmlWebpackPlugin(见下边代码蓝色部分)
- css的路径会自动替换
- js中引用图片的src时,要用require()
图片文件打包
-
在main.js中引用
-
安装loader
npm install url-loader --save-dev
npm install file-loader --save-dev
npm install html-withimg-loader --save-dev
var html = require('html-withimg-loader!./xxx.html');
- 配置
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
outputpath: '' // 指定输出路径
},
{
test: /\.(png|jpg|gif|jpeg)$/,
use: [
{
loader: 'url-loader',
options: {
// 设置引入资源的大小,
// 当加载的图片小于limit时候,会将图片编译成base64字符串形式;
// 当加载的图片大于limit时候,需要使用file-loader模块进行加载
limit: 8 * 1024, // 转化为base64的图片比正常图片要大
name: 'img/[name].[hash:8].[ext]' // 图片资源命名
}
},
{
loader: 'file-loader'
}
]
},
{
test: /\.(htm?l)/i,
use: {loader: 'html-withimg-loader'}
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: 'html-withimg-loader!' + path.resolve(srcDir, filename),
filename: filename
}),
]
4. 设置
output: {
...
publicPath: 'dist/'
}
可以在打包时候自动更改图片的路径
Vue文件编译处理
安装:
npm install vue-loader vue-template-compiler --save-dev
配置:
{
test: '/\.vue$',
use: ['vue-loader']
}
其他资源处理
npm i file-loader --save-dev
配置:
{ test: Condition }:匹配特定条件。一般是提供一个正则表达式或正则表达式的数组,但这不是强制的。
{ include: Condition }:匹配特定条件。一般是提供一个字符串或者字符串数组,但这不是强制的。
{ exclude: Condition }:排除特定条件。一般是提供一个字符串或字符串数组,但这不是强制的。
{ and: [Condition] }:必须匹配数组中的所有条件
{ or: [Condition] }:匹配数组中任何一个条件
{ not: [Condition] }:必须排除这个条件
配置开发环境或者生产环境的兼容性问题
"browserslist": {
// 开发环境 --> 设置node环境变量:process.env. NODE_ENV = development
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
],
// 生产环境:默认是看生产环境
"production": [
">0.2%",
"not dead",
"not op_mini all"
]
}
plugin插件
- plugin是插件,通常是用于对某个现有框架进行扩展。
- loader和plugin区别
- loader主要用于转换某些类型的模块,它是一个转换器。
- plugin是插件,它是对webpack本身的扩展,是一个扩展器。
CSS文件分离插件 mini-css-extract-plugin
配置
const HtmlWebpackPlugin = require('html-webpack-plugin'); // HTML处理插件
const MiniCSSExtractPlugin = require('mini-css-extract-plugin'); // CSS处理插件
const webpack = require('webpack'); //访问内置的插件
const path = require('path');
module.exports = {
entry: './path/to/my/entry/file.js',
output: {
filename: 'my-first-webpack.bundle.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
use: 'babel-loader'
}
]
},
plugins: [
new webpack.ProgressPlugin({ // HTML处理
template: 'index.html'
}),
new HtmlWebPlugin({ // HTML文件处理
template: './src/index.html' // 复制index.html文件
}),
new MiniCSSExtractPlugin(), // 样式处理
new webpack.BannerPlugin({ // 添加横幅
banner: 'hello world'
})
]
};
压缩丑化uglifyjs-webpack-plugin
下载:
npm install [email protected] --save-dev
配置:
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
optimization: {
minimizer: [new UglifyJsPlugin()],
},
};
下载:
npm install [email protected] --save-dev
配置:
// webpack.config.js
devServer: {
contentBase: './dist/, // 为哪个文件夹提供本地服务
port: 8080, // 指定端口号
inline: true, // 页面实时刷新
compress: true,// 是否开启服务端压缩(gzip)
// historyApiFallback 在SPA页面,依赖HTML5的history模式
}
// pages.js
"scripts": {
"dev": "webpack-dev-server --open"
},
配置分离
关于mode
webpack根据开发和生成环境一般可以将配置文件拆分,拆分dev和prod两种环境
|- package.json
|- /build
|- webpack.base.js
|- webpack.dev.js
|- webpack.prod.js
在scripts里修改相应的命令
"dev": "webpack-dev-server --config build/webpack.dev.js",
"build": "webpack --config build/webpack.prod.js"
使用webpack-merge,用以合并通用配置文件与开发环境配置文件
// webpack.dev.js
const path = require('path');
const webpack = require('webpack');
const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base');
module.exports = merge(baseWebpackConfig, {
mode: 'development',
devServer: {
host: '127.0.0.1',
port: 80,
contentBase: path.join(__dirname, 'dist'),
open: false,
hot: false,
disableHostCheck: true,
proxy: {},
before () {}
},
plugins: [
// 启用 HMR
new webpack.HotModuleReplacementPlugin({})
]
});
// webpack.prod.js
const baseWebpackConfig = require('./webpack.base');
module.exports = merge(baseWebpackConfig, {
mode: 'production'
});