webpack.config.js
const path = require("path"); // node 内置模块
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin"); // 使用html模板
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); // css文件单独压缩到独立的css文件中
const OptimizeCssAssetsWebpackPlugin = require("optimize-css-assets-webpack-plugin"); // 压缩打包出来的css文件
const UglifyJsPlugin = reuqire("ugligyjs-webpack-plugin"); // 压缩打包出来的js文件, 默认js文件是压缩的,但是配置css压缩后js就不会再默认压缩,
const CleanWebpackPlugin = require("clean-webpack-plugin"); // 清除已打包文件
const CopyWebpackPlugin = require("copy-webpack-plugin"); // 拷贝文件夹
const Happypack = require("happypack"); // 多线程打包
module.exports = {
mode: "development",
entry: "./src.index.js",
output: {
filename: "bundle.[hash:8].js",
path: path.resolve(__dirname, "dist"), // 必须是绝对路径
publicPath: "" // 公共路径,所有资源引入时加上这个路径
},
// 增加映射文件,便于调测
devtool: "source-map",
// 启用监控
watch: true,
watchOptions: {
poll: 1000, // 每秒更新多少次
aggreateTimeout: 500, // 防抖, 一直输入时不触发
ignored: /node-modules/ // 不需要监控的文件
},
// 打包优化项, 开发环境建议不用
optimization: {
// 压缩代码
mininizer: [
new UglifyJsPlugin({
cache: true, // 启用缓存
parallel: true, // 是否并发打包
sourceMap: true
}),
new OptimizeCssAssetsWebpackPlugin()
],
// 优化:抽离公共代码
splitChunks: {
cacheGroups: {
// 公共模块
common: {
chunks: "initial",
minSize: 0, // 文件大小
minChunks: 2 // 引用次数
},
// 第三方模块
vernder: {
priority: 1, // 执行优先级:权重
test: /node_modules/,
chunks: "initial",
minSize: 0, // 文件大小
minChunks: 2 // 引用次数
}
}
}
},
module: {
npParse: /jQuery/, // 优化:不去解析的依赖
rules: [
{
test: /\.less$/,
// css-loader: 解析@import语法
// style-loader: css插入到head标签中
// less-loader: less转为css
use: [
// "style-loader", // 插入到了header最下面,默认
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {}
},
{
loader: "less-loader"
},
"postcss-loader" // 自动补充css样式兼容性前缀, 配合autoperfixer包
] // 默认从右向左执行
},
{
test: /\.js$/,
exclude: /node_modules/, // 优化:
include: "/src",
use: {
loader: "babel-loader", // 把js的es6语法转换为es5语法
options: {
// 预设成的语法包
presets: ["@babel/perset-env", "@babel/preset-react"], // @babel/preset-react 解析react
plugins: [
// 解决装饰器无法正确解析的问题
[
"@babel/plugin-proposal-decorators",
{ legacy: true }
],
// ES高级语法解析插件
[
"@babel/plugin-proposal-class-properties",
{
loose: true
}
],
// 解决工厂函数generator不能正确解析的问题: 抽离公共方法
"@babel/plugin-transform-runtime",
// 使用import 实现动态加载
"@babel/plugin-syntax-dynamic-import"
]
}
},
include: path.resolve(__dirname, "src")
},
// js代码检测
{
use: /\.js$/,
use: {
loader: "eslint-loader", // 注意此加载器的顺序
options: {
enforce: "pre" // 强制: 最先执行(pre) / post 之后执行
}
}
},
// 模块暴露为全局
{
test: require.reaolve("jquery"),
use: "expose-loader?$"
},
//引入图片
{
test: /\.(png|jpg|gif)$/,
use: {
// 可以增加限制,满足条件转换为 base64 的图片, 不满足限制自动使用 file-loader
loader: "url-loader", //
options: {
limit: 200 * 1024,
outpurPath: "/images"
}
}
},
// html文件 img 标签图片的引入
{
test: /\.html$/,
use: "html-withimg-loader"
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: "./index.html",
filename: "index.html",
minify: {
// 对html文件压缩处理
removeAttributeQuotes: true, // 删除双引号
collapseWhitespace: true // 折行显示
},
hash: true
}),
new MiniCssExtractPlugin({
// 可以使用多个打包出多个css文件
filenane: "/css/main.css"
}),
// 在每个模块中都注入$符
new webpack.ProvidePlugin({
$: "jquery"
}),
new CleanWebpackPlugin("./dist"), // 清空的文件夹
new CopyWebpackPlugin([
{
from: "./src/assets",
to: "./assets"
}
]),
//版权声明
new webpack.BannerPlugin("版权声明内容 copyRight of my "),
// 定义环境变量
new webpack.DefinePlugin({
DEV: JSON.stringify("development"), // 字符串
FLAG: "true" // bool值
}),
// 优化:打包是不引入moment内部的locale的文件
new webpack.IgnorePlugin(/\.\/locale/, /moment/),
// 优化:先去此路径找依赖,没有再去打包依赖
new webpack.DllReferencePlugin({
manifest: path.resolve(__dirname, "dist", "manifest.json") // 任务清单
}),
// 热更新插件
new webpack.HotModuleReplacementPlugin(),
// 打印更新的模块路径
new webpack.NamedModulesPlugin()
],
// 配置不需要打包的模块
externals: {},
// 指定解析的第三方包的位置
resolve: {
modules: [path.resolve("node-modules"), path.resolve("")],
// 设置路径别名
alias: {
"@": "./src"
},
mainFields: ["style", "main"], //入口文件顺序 package.json中查看文件类型
mainFiles: ["index.js"], // 入口文件的名字
extensions: [".js", ".css", ".json"] // 文件拓展名, 从左到右依次查找
},
devServer: {
port: 3000,
progress: true,
contentBase: "./build", // 打包的静态文件保存的文件夹
compress: true, // 启用压缩
hot: true,
// 配置代理
proxy: {
"/api": {
target: "http://localhost:3001",
pathRewrite: { "/api": "" } // 重写请求地址
}
},
// 提供的钩子方法,直接起mock服务器
before(app) {
app.get("/api", (req, res) => {});
}
}
};
postcss.config.js
// 配置postcss-loader
module.exports = {
plugins: [require("autoperfixer")]
};
webpack-dev-server + mockServer
const express = requrie("express");
const webpack = requyire("webpack");
const middle = requrie("webpack-dev-middleware");
const config = requrie("./webpack.config.js");
// http-proxy 服务器处理
const app = express();
// 使用打包后的资源, 使服务端和前端代码都起在服务端
let complier = webpack(config);
app.use(middle(complier));
app.get();
app.listen(3001);
安装
本地:webpack webpack-cli webpack-dev-server
@babel-polfill 解决无法正确解析更高级语法的问题
eslint 配置文件可通过官网自动生成
引入第三方模块的集中方法:
- expose-loader: 暴露到 window 对象上;
- providePlugin: 注入到每一个模块中
- 全局引入,不打包
图片的引入
- file-loader
- html-withimg-loader // 引入 img 标签的图片
- url-loader
devtool 可配置选项
- source-map: 大和全,源码映射
- eval-source-map: 不会产生单独的文件,但是可以显示行和列
- cheap-module-source-map: 不会产生列但是会产生一个单独的映射文件
- cheap-module-eval-source-map: 不会产生文件集成在打包后的文件中,也不会产生列
merge
module.exports = merge(common, {})
优化:
happypack 多线程打包: 大项目打包时使用
{ test: /.js$/, use: "Happypack/loader?id=js" }
new Happypack({ id: "js", use: [{ loader: "babel-loader", options: { presets: [ "@babel/presert-env", "@babel/preset-react" ] } }] })
production 模式下:
tree-shaking: 把没用到的代码自动删除掉 必须使用: import 的方法引入
scope hosting: 在 webpack 中自动忽略一些可以简化的代码
动态加载
@babel/plugin-syntax-dynamic-import
import("./app.js").then(data => {
data.default; // 获取数据
});
热更新
if(module.hot){
module.hot.accept("./dd.js", () => {
// 文件更新后执行
const data = require("./source").default;
});
}