webpack 四个核心概念
- Entry:入口起点(entry point)指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始
- Output:output 属性告诉 webpack 在哪里输出它所创建的 bundles,以及如何命名这些文件,默认值为 ./dist
- Loader:loader 让 webpack 能够去处理那些非 JavaScript 文件(webpack 自身只能解析: JavaScript、json)
- Plugins:插件则可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量等
Webpack 本身只能加载 JS/JSON 模块,如果要加载其他类型的文件(模块),就需要使用对应的 loader 进行转换/加载
Loader 本身也是运行在 node.js 环境中的 JavaScript 模块,它本身是一个函数,接受源文件作为参数,返回转换的结果。
loader 一般以 xxx-loader 的方式命名,xxx 代表了这个 loader 要做的转换功能,比如 sass-loader
插件件可以完成一些 loader 不能完成的功能,插件的使用一般是在 webpack 的配置信息 plugins 选项中指定
- CleanWebpackPlugin: 自动清除指定文件夹资源
- HtmlWebpackPlugin: 自动生成 HTML 文件
- UglifyJSPlugin: 压缩 js 文件
webpack.config.js : 是一个 node 模块,返回一个 json 格式的配置信息对象
结论:
- webpack 能够编译打包 js 和 json 文件
- 能将 es6 的模块化语法转换成浏览器能识别的语法
- 能压缩代码
缺点:
- 不能编译打包 css、img 等文件
- 不能将 js 的 es6 基本语法转化为 es5 以下语法
改善:使用 webpack 配置文件解决,自定义功能
入口及出口配置
根目录下执行yarn init -y
,yarn add webpack@4 webpack-cli@3 -D
在根目录下新建文件夹 config,在 config 文件夹下创建webpack.dev.js
与webpack.prod.js
,在这两个文件下配置 webpack
const { resolve } = require("path"); module.exports = { // 工作模式 development|production mode: "development", // 入口 entry: "./src/js/index.js", // 输出 output: { path: resolve(__dirname, "../dist"), filename: "./js/index.js", }, };
在 package.json 中添加
"scripts": { "build": "webpack --config ./config/webpack.prod.js" },
解析 less
安装:yarn add less less-loader css-loader style-loader -D
在webpack.prod.js
中配置
module.exports = { module: { rules: [ // 解析less { test: /\.less$/, // 匹配所有的less文件 use: [ "style-loader", // 用在html文档中创建一个style标签,将样式塞进去 "css-loader", // 将less编译后的css转换成为CommonJs的一个模块 "less-loader", // 将less编译为css,但不生成单独的css文件,在内存中 ], }, ], }, };
eslint语法检查
安装:yarn add eslint eslint-loader -D
配置loader:
module.exports = { rules:[ { test: /\.js$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env'] } } } ] }
在package.json中配置eslint的检查规则(注释需去掉)
"eslintConfig": { "parserOptions": { "ecmaVersion": 6, // 支持es6 "sourceType": "module" // 使用es6模块化 }, "env": { // 设置环境 "browser": true, // 支持浏览器环境:能够使用window上的全局变量 "node": true // 支持服务器环境:能够使用node上的全局变量 }, "globals": { // 声明使用的全局变量,这样即使没有定义也不会报错了 "$": "readonly" // 只读变量 }, "rules": { "no-console": 0, // 不检查console "eqeqeq": 2, // 用==而不用===就报错 "no-alert": 2 // 不能使用alert }, "extends": "eslint:recommended" // 使用eslint推荐的默认规则:https://cn.eslint.org/docs/rules/ }
js语法转换
webpack只管翻译ES6的模块语法变为浏览器认识的,但是不会处理其它新语法
安装:yarn add babel-loader @babel/core @babel/preset-env -D
配置loader:
module.exports = { module:{ rules:[ { test: /\.js$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env'] } } } ] } }
js兼容性处理
使用polyfill
安装:yarn add @babel/polyfill
使用:在index.js中引入
import '@babel/polyfill'
优点:解决babel只能转换部分低级语法的问题(如:let/const/解构赋值),引入polyfill可以转换高级语法(如:Promise)
缺点:将所有高级语法都进行了转换,但实际上可能只使用一部分
core-js按需引入
安装:yarn add core-js -D
配置loader:
module.exports = { rules:[ { test: /\.js$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: [ ['@babel/preset-env', { useBuiltIns: 'usage', // 按需引入polyfill corejs: { version: 3 }, // 解决warn targets: { // 指定兼容性处理哪些浏览器 "ie": "9", "chrome": "58" } }] ], cacheDirectory: true // 开启babel缓存 } } } ] }
处理图片资源
安装:yarn add url-loader -D
在webpack.prod.js
中配置
module.exports = { module:{ rules:[ { test: /\.(png|jpg|gif)$/, use: [ { loader: 'url-loader', options: { limit: 8192,// 8kb --> 8kb以下的图片会base64处理 publicPath: '../dist/images', // 决定图片的url路径 outputPath: 'images', // 决定文件本地输出路径 name: '[hash:5].[ext]' // 修改文件名称 [hash:8] hash值取8位 [ext] 文件扩展名 }, } ] } ] } }
打包 html 文件
html 文件 webpack 不能解析,需要借助插件编译解析
添加 html 文件,src/index.html
,注意不要在 html 中引入任何 css 和 js 文件
添加插件 htmlWebpackPlugin
yarn add html-webpack-plugin -D
在webpack.prod.js
中引入插件,插件需要手动引入,loader 会自动加载
配置插件
const HtmlWebpackPlugin = require("html-webpack-plugin"); module.exports = { plugins: [ new HtmlWebpackPlugin({ template: "./src/index.html", // 以当前文件为模板创建新的html(结构和原来一样,会自动引入打包的资源) }), ], };
打包html中图片资源
html中的图片url-loader没法处理,它只能处理js中引入的图片、样式中图片,不能处理html中img标签,需要引入html-loader处理
安装:yarn add html-loader -D
配置loader:
module.exports = { module:{ rules:[ { test: /\.html$/i, loader: 'html-loader', } ] } }
打包其它资源
如:字体图标…
安装:yarn add file-loader -D
配置loader:
module.exports = { module:{ rules:[ { test: /\.(eot|svg|woff|woff2|ttf|mp3|mp4|avi)$/, // 处理其他资源 loader: 'file-loader', options: { outputPath: 'media', name: '[hash:5].[ext]' } } ] } }
清除打包文件目录
每次打包生成了文件都需要手动删除,引入插件帮助我们自动删除上一次的文件
安装:yarn add clean-webpack-plugin -D
webpack.prod.js 中配置
const { CleanWebpackPlugin } = require("clean-webpack-plugin"); // 注意解构赋值 module.exports = { plugins: [ new CleanWebpackPlugin(), // 自动清除output.path目录下的文件 ], };
自动编译打包运行
安装:yarn add webpack-dev-server -D
修改webpack配置对象:
module.exports = { devServer: { open:true, // 自动打开浏览器 compress:true, // 启动gzip压缩 port: 8000 // 端口号 } }
修改url-loader部分配置,因为构建工具以build为根目录,不用再找build了,publicPath: '../dist/images'
修改成publicPath:'/images/
在package.json中添加:
"script":{ "start": "webpack-dev-server --config ./config/webpack.dev.js" }
热模替换功能
热模替换功能(模块热更新)允许在运行时更新所有类型的模块,而无需完全刷新(只更新变化的模块,不变的模块不更新)
详细配置官网->指南->模块热替换
修改devServer配置
devServer: { open: true, // 自动打开浏览器 compress: true, // 启动gzip压缩 port: 8000, // 端口号 hot: true // 开启热模替换功能 HMR },
问题:html文件无法自动更新了,需要增加一个入口
entry: ['./src/js/index.js', './src/index.html']
devtool
devtool一种将压缩/编译文件中的代码映射回源文件的原始位置的技术,让我们调试代码不在困难
- cheap只保留行,编译速度快
- eval webpck生成的代码(每个模块彼此分开,并使用模块名称进行注释),编译速度快
- inline以base64方式将source-map嵌入到代码中,缺点造成编译后代体积很大
推荐使用:
- 开发环境:eval-cheap-module-source-map
- 生产环境:cheap-module-source-map
生产环境代码需要部署到服务器上才能运行,serve这个库能帮助我们快速搭建一个静态资源服务器
yarn add serve -g
serve -s build -p 8000
提取css成单独文件
安装插件:yarn add mini-css-extract-plugin -D
引入插件:const MiniCssExtractPlugin = require('mini-css-extract-plugin')
配置loader:
{ test: /\.less$/i, use: [ MiniCssExtractPlugin.loader, 'css-loader', // 将less编译后的css转换成为CommonJs的一个模块。 'less-loader' //将less编译为css,但不生成单独的css文件,在内存中。 ], }
配置插件:
const MiniCssExtractPlugin = require('mini-css-extract-plugin') module.exports = { plugins:[ new MiniCssExtractPlugin({ filename: 'css/[hash:5].css' }) ] }
添加css兼容
安装:yarn add postcss-loader@3.0.0 postcss-flexbugs-fixes@4 postcss-preset-env postcss-normalize autoprefixer -D
配置loader:
module.exports = { rules:[ { test: /\.less$/i, use: [ MiniCssExtractPlugin.loader, 'css-loader', // 将less编译后的css转换成为CommonJs的一个模块。 { loader: 'postcss-loader', options: { ident: 'postcss', plugins: () => [ require('postcss-flexbugs-fixes'), require('postcss-preset-env')({ autoprefixer: { flexbox: 'no-2009', }, stage: 3, }), require('postcss-normalize')(), ], sourceMap: true, }, }, 'less-loader' //将less编译为css,但不生成单独的css文件,在内存中。 ], } ] }
添加配置文件:.browserslistrc
# Browsers that we support last 1 version > 1% IE 10 # sorry
压缩css
安装:yarn add optimize-css-assets-webpack-plugin -D
配置插件:
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin') module.exports = { pluins:[ new OptimizeCssAssetsPlugin({ cssProcessorPluginOptions: { preset: ['default', { discardComments: { removeAll: true } }], }, cssProcessorOptions: { // 解决没有source map问题 map: { inline: false, annotation: true, } } }) ] }
压缩html
修改插件htmlWebpackPlugin
module.exports = { plugin:[ new HtmlWebpackPlugin({ template: './src/index.html', // 以当前文件为模板创建新的HtML(1. 结构和原来一样 2. 会自动引入打包的资源) minify: { removeComments: true, //移除注释 collapseWhitespace: true, //折叠所有留百 removeRedundantAttributes: true, //移除无用的标签 useShortDoctype: true, //使用短的文档声明 removeEmptyAttributes: true, //移除空标签 removeStyleLinkTypeAttributes: true, //移除rel="stylesheet" keepClosingSlash: true, //自结束 minifyJS: true, minifyCSS: true, minifyURLs: true, } }) ] }