webpack官网 webpack
安装nodejs
如何安装自己看官网教程,webpack依赖于nodejs
初始化文件
创建文件夹 eg:webpack_sudy
打开终端 npm init -y
创建源文件src
在webpack_study文件下
建立src文件夹
src文件夹下创建index.js入口文件,自己输入点内容index.js
打包js文件
输入webpack
或 webpack 打包文件 -o 输出文件 --mode=development
eg(webpack ./src/index.js -o ./build/main.js –mode=development)
建立一个html文件,引入打包文件js即可看到是否打包成功
创建打包配置文件webpack.config.js
const path = require('path'); module.exports = { // 输入 entry: './src/index.js', // 输出 output: { filename: 'main.js', path: path.resolve(__dirname, 'build') }, // loader配置 module: { }, plugins: [ ], mode: 'development', }
基本属性结构如上,根据配置再补充
打包css文件
webpack不能打包css文件,需要解除loader
配置如下,即在上面module:{}里面配置
// loader配置 module: { rules: [ // 打包css文件 { test: /\.css$/, use: [ 'style-loader', 'css-loader' ] }, //打包less文件 { test: /\.less$/, use: [ 'style-loader', 'css-loader', 'less-loader' ] }, ] },
在js里面import ‘css文件’
建立一个html文件,引入打包文件js即可看到是否打包成功
打包html文件
需要借助插件html-webpack-plugin
安装html-webpack-plugin
安装命令 -D为本地安装
npm install html-webpack-plugin -D
webpack.config.js配置
//开头引入 const HtmlWebpackPlugin = require('html-webpack-plugin'); //之后在里面plugins属性里面配置 plugins: [ // 使用插件html-webpack-plugin打包html文件 // new HtmlWebpackPlugin()打包多一个index.html文件 new HtmlWebpackPlugin({ // 复制入门文件index.html结构样式 template: './src/index.html' }) ],
打包运行
命令 webpack
即可看到打包文件中多了一个index.html
打包图片文件
气死了气死了气死了,卡了好久好久不能正常显示,原来是版本太高的问题,呕血!!!!!
注意:推荐使用版本较低的,比如以下版本,于是实在出问题摸不着头脑的时候便按照以下图片修改了版本
重新安装版本
npm i css-loader@5.2.4 -D
npm i style-loader@2.0.0 -D
css中的图片背景
( 使用url-loader,url-loader依靠file-loader)
下载安装 npm i url-loader file-loader -D
在module里面配置rules:[{}]
// 打包css中url图片文件 { test: /\.(jpg|png|gif)$/i, // url-loader依靠file-loader所以需要下载两个 loader: 'url-loader', options: { // 设置图片小于6*1024,就会被base64处理图片,减少请求数量 limit: 6 * 1024, // 关闭url-loader的es6模块化,不然html里面img元素会有问题 esModule: false, // [ext]取原来扩展名 名字长度取10 name: '[name].[hash:10].[ext]', // 超过大小file-loader打包 fallback: 'file-loader', outputPath: 'images/', } },
html里面的img
使用html-loader(加配置,可能会出错)或
html-withimg-loader
安装 npm i html-loader -D 或
npm i html-withimg-loader -D
在module里面配置rules:[{}]
用html-loader配置
// 打包html文件img问题 { test: /\.html$/, loader: 'html-loader', options: { esModule: false } }
用html-withimg-loader(推荐这个)
{ test: /\.html$/, loader: 'html-withimg-loader' }
打包其他资源
(其他资源:不需要做任何处理,原封不动输出出去就可以)
打包字体图标示例
这里使用iconfont阿里云矢量图标库
下载解压引入iconfont.css 在入口文件 index.js 设置
import ‘’iconfont.css路径“
看到iconfont.css中需要几个文件一同引入过来
(utl根据实际情况更改)
引入目录为(有些还需要svg,看iconfont.css需要什么)
于是在index.html配置引用
(本人在这里傻逼了,class没写,一直还以为哪里出错)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>webpack打包文件</title> </head> <body> <div>webpack打包</div> <h2>其他资源打包</h2> <span class="iconfont icon-shezhi"></span> <span class="iconfont icon-dingdan"></span> <span class="iconfont icon-shangpin"></span> <span class="iconfont icon-yonghuqun"></span> <span class="iconfont icon-quanxian"></span> </body> </html>
webpack.config.js module中rules:[{}]配置为
// 打包其他资源 { exclude: /\.(css|less|js|html|jpg|png|gif)$/, loader: 'file-loader', options: { //输出文件夹 outputPath: 'others' } }
打包运行命令webpack 打包成功
devServer
帮助自动打包,修改代码后,不需要每次webpack打包
-
安装工具webapck-dev-server npm i webpack-dev-server -D
-
配置命令mode属性同级下配置
// 开发服务器devServer 用来自动化 // 特点:只会在内存中编译打包,不会有任何输出 // 启动命令为 npx webpack-dev-server devServer: { // contentBase: path.resolve(__dirname, 'dist'),//官方文档已经说被弃用 }, // 启动gzip压缩 compress: true, // 启动端口号 port: 3001, //自动打开浏览器 open: true, }
-
运行命令 npx webpack-dev-server
在源文件src里面修改代码保存即自动打包,刷新浏览器即可看到(建立安装vscode自动刷新插件---Live Server,实现保存即可看到浏览器内容,无须刷新)
下载好在需要监听的html文件右键,选择 open with Live Server
以上打包完整代码
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { // 输入 entry: './src/index.js', // 输出 output: { // 输出目录 path: path.resolve(__dirname, 'dist'), filename: 'bundle.js', }, // loader配置 module: { rules: [ // 打包css文件 { test: /\.css$/, use: [ 'style-loader', 'css-loader' ] }, //打包less文件 { test: /\.less$/, use: [ 'style-loader', 'css-loader', 'less-loader' ] }, // 打包css中url图片文件 { test: /\.(jpg|png|gif|svg)$/i, // url-loader依靠file-loader所以需要下载两个 loader: 'url-loader', options: { // 设置图片小于6*1024,就会被base64处理图片,减少请求数量 limit: 6 * 1024, // 关闭url-loader的es6模块化,不然html里面img元素会有问题 esModule: false, // [ext]取原来扩展名 名字长度取10 name: '[name].[hash:10].[ext]', // 输出文件夹 outputPath: 'images', } }, // 打包html文件img问题 { test: /\.(htm|html)$/, loader: 'html-withimg-loader' }, // 打包其他资源 { exclude: /\.(css|less|js|html|jpg|png|gif)$/, loader: 'file-loader', options: { //输出文件夹 outputPath: 'others' } } ] }, plugins: [ // 使用插件html-webpack-plugin打包html文件 // new HtmlWebpackPlugin()打包多一个index.html文件 new HtmlWebpackPlugin({ // 复制入门文件index.html结构样式 template: './src/index.html' }) ], mode: 'development', // 开发服务器devServer 用来自动化 // 特点:只会在内存中编译打包,不会有任何输出 // 启动命令为 npx webpack-dev-server devServer: { // contentBase: path.resolve(__dirname, 'dist'),//官方文档已经说被弃用 //可写可不写 static: { directory: path.join(__dirname, 'dist'), }, // 启动gzip压缩 compress: true, // 启动端口号 port: 3001, //自动打开浏览器 open: true, } }
多文件配置
这里以index.html和login.html为例子
-
配置多个入口
// 多文件配置多个入口 entry: { index: './src/index.js', login: './src/login.js' },
-
配置多个输出
output: { // 多文件输出 path: path.resolve(__dirname, 'dist'), filename: 'js/[name].js', },
-
复制多个html文件
plugins: [ // 使用插件html-webpack-plugin打包html文件 // new HtmlWebpackPlugin()打包多一个index.html文件 new HtmlWebpackPlugin({ // 复制入门文件index.html结构样式 template: './src/index.html', filename: 'index.html', chunks: ['index'] }), // 多文件 new HtmlWebpackPlugin({ // 复制入门文件login.html结构样式 template: './src/login.html', filename: 'login.html', chunks: ['login'] }) ],
完整代码为:
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { // 输入 // entry: './src/index.js', // 多文件配置多个入口 entry: { index: './src/index.js', login: './src/login.js' }, // 输出 output: { // 输出目录 // path: path.resolve(__dirname, 'dist'), // filename: 'bundle.js', // 多文件输出 path: path.resolve(__dirname, 'dist'), filename: 'js/[name].js', }, // loader配置 module: { rules: [ // 打包css文件 { test: /\.css$/, use: [ 'style-loader', 'css-loader' ] }, //打包less文件 { test: /\.less$/, use: [ 'style-loader', 'css-loader', 'less-loader' ] }, // 打包css中url图片文件 { test: /\.(jpg|png|gif|svg)$/i, // url-loader依靠file-loader所以需要下载两个 loader: 'url-loader', options: { // 设置图片小于6*1024,就会被base64处理图片,减少请求数量 limit: 6 * 1024, // 关闭url-loader的es6模块化,不然html里面img元素会有问题 esModule: false, // [ext]取原来扩展名 名字长度取10 name: '[name].[hash:10].[ext]', // 输出文件夹 outputPath: 'images', } }, // 打包html文件img问题 { test: /\.(htm|html)$/, loader: 'html-withimg-loader' }, // 打包其他资源 { exclude: /\.(css|less|js|html|jpg|png|gif)$/, loader: 'file-loader', options: { //输出文件夹 outputPath: 'others' } } ] }, plugins: [ // 使用插件html-webpack-plugin打包html文件 // new HtmlWebpackPlugin()打包多一个index.html文件 new HtmlWebpackPlugin({ // 复制入门文件index.html结构样式 template: './src/index.html', //输出文件名字 filename: 'index.html', //打包优化 chunks: ['index'] }), // 多文件 new HtmlWebpackPlugin({ // 复制入门文件login.html结构样式 template: './src/login.html', //输出文件名字 filename: 'login.html', //打包优化 chunks: ['login'] }) ], mode: 'development', // 开发服务器devServer 用来自动化 // 特点:只会在内存中编译打包,不会有任何输出 // 启动命令为 npx webpack-dev-server devServer: { // contentBase: path.resolve(__dirname, 'dist'),//官方文档已经说被弃用 }, // 启动gzip压缩 compress: true, // 启动端口号 port: 3001, //自动打开浏览器 open: true, } }
多文件打包成功
babel配置
babel:将高版本的js语法转换为低版本浏览器能识别的语法
-
安装
npm i babel-loader @babel/core @babel/preset-env -D
再安装 否则处理不了对象的方法( 比如eg:arr.includes(4) )
npm i @babel/polyfill -S
-
配置
// babel转换 { test: /.\js$/, loader: 'babel-loader', exclude: /node_modules/, options: { presets: ['@babel/env'] } },
index.js中引入对象的方法处理
import '@babel/polyfill'
-
打包 看看打包的js文件中是否将高版本语法转换为低版本语法
sourceMap源码映射
源码的映射,通过sourceMap打包找到真正源码的位置
-
解决编出来的源码位置并不是实际的位置,比如
问题:点击上图右侧,并不是真正index.js映射的源码位置
面试官问map文件是什么?就是sourceMap源码映射
详情官网 Devtool | webpack
配置如下:(开发模式下建立用3不生成map文件且为源码)
devtool:'eval-cheap-module-source-map'
使用第三方插件
全局使用第三方插件 比如jquery $
下载第三方插件
npm i jquery -S
配置webpack自带插件
const webpack = require('webpack'); //plugins里面配置 plugins:[ // 第三方库jquery挂载使用 new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery' }) ]
在js文件直接使用即可实现
webpack区分生产环境和开发分包
-
分包 建立 build目录同级,划分三个文件,分别为webpack.base.js webpack.dev.js webpack.pro.js
-
安装分包工具wepack-merge,合并配置文件
npm i webpack-merge -D
-
修改配置文件合并内容
-
webpack.base.js(完整代码参考)
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const webpack = require('webpack'); module.exports = { // 输入 // entry: './src/index.js', // 多文件配置多个入口 entry: { index: './src/index.js', login: './src/login.js' }, // 输出 output: { // 输出目录 // path: path.resolve(__dirname, 'dist'), // filename: 'bundle.js', // 多文件输出 path: path.resolve(__dirname, '..', 'dist'), filename: 'js/[name].js', }, // loader配置 module: { rules: [ // 打包css文件 { test: /\.css$/, use: [ 'style-loader', 'css-loader' ] }, //打包less文件 { test: /\.less$/, use: [ 'style-loader', 'css-loader', 'less-loader' ] }, // 打包css中url图片文件 { test: /\.(jpg|png|gif|svg)$/i, // url-loader依靠file-loader所以需要下载两个 loader: 'url-loader', options: { // 设置图片小于6*1024,就会被base64处理图片,减少请求数量 limit: 6 * 1024, // 关闭url-loader的es6模块化,不然html里面img元素会有问题 esModule: false, // [ext]取原来扩展名 名字长度取10 name: '[name].[hash:10].[ext]', // 输出文件夹 outputPath: 'images', } }, // 打包html文件img问题 { test: /\.(htm|html)$/, loader: 'html-withimg-loader' }, // 打包其他资源 { exclude: /\.(css|less|js|html|jpg|png|gif)$/, loader: 'file-loader', options: { //输出文件夹 outputPath: 'others' } }, // babel转换 { test: /.\js$/, loader: 'babel-loader', exclude: /node_modules/, options: { presets: ['@babel/env'] } }, ] }, //插件 plugins: [ // 使用插件html-webpack-plugin打包html文件 // new HtmlWebpackPlugin()打包多一个index.html文件 new HtmlWebpackPlugin({ // 复制入门文件index.html结构样式 template: './src/index.html', filename: 'index.html', chunks: ['index'] }), // 多文件 new HtmlWebpackPlugin({ // 复制入门文件login.html结构样式 template: './src/login.html', filename: 'login.html', chunks: ['login'] }), // 第三方库jquery挂载使用 new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery' }) ] }
2.webpack.dev.js
const { merge } = require('webpack-merge'); const baseConfig = require("./webpack.base.js"); module.exports = merge(baseConfig, { mode: 'development', // 开发服务器devServer 用来自动化 // 特点:只会在内存中编译打包,不会有任何输出 // 启动命令为 npx webpack-dev-server devServer: { // contentBase: path.resolve(__dirname, 'dist'),//官方文档已经说被弃用 // 启动gzip压缩 compress: true, // 启动端口号 port: 3001, //自动打开浏览器 open: true, }, devtool: 'eval-cheap-module-source-map', });
3.webpack.pro.js
const { merge } = require('webpack-merge'); const baseConfig = require("./webpack.base.js"); module.exports = merge(baseConfig, { mode: 'production' });
-
-
增加或修改package.json配置 找到script节点
"scripts": { "server": "webpack-dev-server --config ./build/webpack.dev.js", "build": "webpack --config ./build/webpack.pro.js" },
这样便实现区分了生产环境和开发环境
npm run server //开发模式下 npm run build //生产模式下
webpack处理跨域问题
-
为什么出现跨域?
协议 域名 端口号 三个有一个不一样便出现跨域
-
面试常问问题,如何解决跨域?
CORS(在接口上添加注解,后端处理,但是数据不安全)
JSONP(利用script的src属性,只能处理get请求)
Nginx(反向代理)
使用webpack作代理(比较好的处理方式)
webpack处理跨域配置
在目录下打开终端,安装webpack
npm i webpack webpack-cli -D
初始化 npm init -y
-
推荐方法,在webpack.config.js中devServer节点中,增加一个属性
proxy:{ //检测当请求路径前面为/api时,将会替换为后面的ip "/api":"http://localhost:666" }
-
-
安装axios npm i axios -S
前端请求(需要跨域接口前面用 /api)
// 引入axios const axios = require("axios"); //发请求 axios.get("/api/getList").then(res => { console.log(res); }).catch(err => { console.log(err); })
-
cors方法,但是不安全
//安装 npm i cors //引入 const cors=require(“cors”) //实现 app.use(cors);
-
模拟后台编写简单接口
-
在src同级建立server目录,建立app.js
-
npm init -y
-
npm i express
-
编写后台服务器简单代码,开一个接口
const express = require("express"); const app = express(); app.get("/api/getList", (req, res) => { res.send({ status: 0, message: "请求成功", data: [ { id: 1, name: "张三", age: 20 }, { id: 2, name: "李四", age: 22 }, { id: 3, name: "王五", age: 23 }, ] }) }) app.listen(666, () => { console.log("http://localhost:666/api/getList"); })
点击链接在浏览器即可看到数据
-
在前端src那个文件下载axios发起请求 (eg:在index.js利用axios请求) npm i axios -S
-
在index.js发起请求
// 引入axios const axios = require("axios"); //发请求 axios.get("http://localhost:666/api/getList").then(res => { console.log(res); }).catch(err => { console.log(err); })
-
在server的终端下开启后台 node app.js,在上一级前端目录在开启前端 npm run server(有的是npm run dev,具体看package.json配置)
发现问题跨域!!!
-
具体解决方法请回看上面一点点,简单来说就是在devServer节点配置
proxy:{ "/api":"跨域ip" }
成功解决,跨域请求成功
webpack.config.js跨域配置代码
如下是两个页面index.html和login.html均配置实现了跨域
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const webpack = require('webpack'); module.exports = { // 输入 // entry: './src/index.js', // 多文件配置多个入口 entry: { index: './src/index.js', login: './src/login.js' }, // 输出 output: { // 输出目录 // path: path.resolve(__dirname, 'dist'), // filename: 'bundle.js', // 多文件输出 path: path.resolve(__dirname, 'dist'), filename: 'js/[name].js', }, // loader配置 module: { rules: [ // 打包css文件 { test: /\.css$/, use: [ 'style-loader', 'css-loader' ] }, //打包less文件 { test: /\.less$/, use: [ 'style-loader', 'css-loader', 'less-loader' ] }, // 打包css中url图片文件 { test: /\.(jpg|png|gif|svg)$/i, // url-loader依靠file-loader所以需要下载两个 loader: 'url-loader', options: { // 设置图片小于6*1024,就会被base64处理图片,减少请求数量 limit: 6 * 1024, // 关闭url-loader的es6模块化,不然html里面img元素会有问题 esModule: false, // [ext]取原来扩展名 名字长度取10 name: '[name].[hash:10].[ext]', // 输出文件夹 outputPath: 'images', } }, // 打包html文件img问题 { test: /\.(htm|html)$/, loader: 'html-withimg-loader' }, // 打包其他资源 { exclude: /\.(css|less|js|html|jpg|png|gif)$/, loader: 'file-loader', options: { //输出文件夹 outputPath: 'others' } }, // babel转换 { test: /.\js$/, loader: 'babel-loader', exclude: /node_modules/, options: { presets: ['@babel/env'] } }, ] }, //插件 plugins: [ // 使用插件html-webpack-plugin打包html文件 // new HtmlWebpackPlugin()打包多一个index.html文件 new HtmlWebpackPlugin({ // 复制入门文件index.html结构样式 template: './src/index.html', filename: 'index.html', chunks: ['index'] }), // 多文件 new HtmlWebpackPlugin({ // 复制入门文件login.html结构样式 template: './src/login.html', filename: 'login.html', chunks: ['login'] }), // 第三方库jquery挂载使用 new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery' }) ], mode: 'development', // 开发服务器devServer 用来自动化 // 特点:只会在内存中编译打包,不会有任何输出 // 启动命令为 npx webpack-dev-server devServer: { // contentBase: path.resolve(__dirname, 'dist'),//官方文档已经说被弃用 // 启动gzip压缩 compress: true, // 启动端口号 port: 3001, //自动打开浏览器 open: true, proxy: { "/api": "http://localhost:666" } }, devtool: 'eval-cheap-module-source-map', }
webpack CSS处理
css文件分离
使用插件mini-css-extract-plugin
-
安装插件 npm i mini-css-extract-plugin -D
-
引入require,修改plugin配置
//引入 const MiniCssExtractPlugin=require("mini-css-extract-plugin"); plugins:[ //使用插件 new MiniCssExtractPlugin({ //输出路径和名字 filename:'/css/[name].css' }) ]
-
将style-loader都修改为
{loader:MiniCssExtractPlugin.loader}
css css3语法兼容处理
-
使用postcss-loader autoprefixer
npm i postcss-loader autoprefixer -D
-
module使用 postcss-loader要写在css-loader后面,卸载后面才是前一个调用
-
配置 当前目录下 新建一个文件postcss-config.js
module.exports = { plugins: [require('autoprefixer')({ overrideBrowserslist: [ 'defaults', 'Android 4.1', 'Chrome>31', 'ff>31', 'ie>=8', 'last 2 versions' ] })] }
成功实现兼容处理
css压缩
-
使用optimize-css-assets-webpack-plugin
npm i optimize-css-assets-webpack-plugin -D
-
使用配置,直接在webpack.pro.js里面配置
const OptimizeCssAssetsWepackPlugin = require("optimize-css-assets-webpack-plugin"); // css文件压缩 plugins: [ new OptimizeCssAssetsWepackPlugin() ],
npm run build查看上述css分离兼容压缩功能成功!建议实现一个步骤打包出来看一下再进行下一步
js和html压缩
js压缩
mode:production //生产模式就压缩了js代码
html压缩
在插件中添加minify
new HtmlWebpackPlugin({ // 复制入门文件index.html结构样式 template: './src/index.html', filename: 'index.html', chunks: ['index'], // html压缩 minify: { // 移除空格 collapseWhitespace: true, // 移除注释 removeComments: true } }),