赞
踩
单一原则,一个loader只做一件事
多个loader,从右到左,从下到上开始解析
样式相关的loader
1、less-loader
自动将less转换为CSS
2、postcss-loader
一、什么是postcss
postCSS和sass/less不同, 它不是CSS预处理器、postCSS是一款使用插件去转换CSS的工具。
二、使用到的插件
autoprefixer: 自动添加浏览器样式前缀
require("autoprefixer")({ "overrideBrowserslist": [ "ie >= 8", // 兼容IE7以上浏览器 "Firefox >= 3.5", // 兼容火狐版本号大于3.5浏览器 "chrome >= 35", // 兼容谷歌版本号大于35浏览器, "opera >= 11.5", // 兼容欧朋版本号大于11.5浏览器 ] })postcss-px2rem-exclude: 自动把px代为转换成rem
原插件为(postcss-px2rem 该插件支持排除文件)
require("postcss-px2rem-exclude")({ remUnit: 100, // 注意算法,这是750设计稿,html的font-size按照750比例 exclude: /node_modules/i, })
3、css-loader
css-loader
会对@import
和url()
进行处理,就像 js 解析import/require()
一样。
4、MiniCssExtractPlugin.loader
MiniCssExtractPlugin.loader mini-css-extract-plugin插件快速入门
作用:从css文件中提取css代码到单独的文件中,对css代码进行代码压缩等
配置:
{ loader: MiniCssExtractPlugin.loader, options: { // 这里可以指定一个 publicPath // 默认使用 webpackOptions.output中的publicPath // publicPath的配置,和plugins中设置的filename和chunkFilename的名字有关 // 如果打包后,background属性中的图片显示不出来,请检查publicPath的配置是否有误 publicPath: './', // publicPath: devMode ? './' : '../', // 根据不同环境指定不同的publicPath hmr: devMode, // 仅dev环境启用HMR功能 } }
style-loader 的功能就一个,在 DOM 里插入一个 <style> 标签,并且将 CSS 写入这个标签内。
babel-loader
什么是babel:Babel 是一个 JavaScript 编译器,它是一个工具链,主要的用途就是在旧的浏览器或环境中将ECMAScript 2015+ 代码转换为向后兼容的 js 代码。
预设和插件:babel转换代码的依据
presets
:执行的转换顺序是从下到上,从右到左@babel/preset-env : 用于编译 ES2015+ 语法
@babel/preset-react : 用于 React
配置:
{ test: /\.(js|jsx)$/, loader: require.resolve("babel-loader"), exclude: [path.resolve("node_modules")], options: { presets: [ require("@babel/preset-env").default, require("@babel/preset-react").default ], plugins: [ // 装饰器插件 ["@babel/plugin-proposal-decorators", { "legacy": true }], ["@babel/plugin-proposal-class-properties", { "loose": false }], // babel运行时 require("@babel/plugin-transform-runtime").default, ], sourceType: 'unambiguous' }, }@babel/plugin-transform-runtime有三大作用:
1.自动移除语法转换后内联的辅助函数(inline Babel helpers),使用@babel/runtime/helpers里的辅助函数来替代;
2.当代码里使用了core-js的API,自动引入@babel/runtime-corejs3/core-js-stable/,以此来替代全局引入的core-js/stable;
3.当代码里使用了Generator/async函数,自动引入@babel/runtime/regenerator,以此来替代全局引入的regenerator-runtime/runtime;
处理js之外的资源文件,如图片 字体等
url-loader 可以识别图片的大小,超过配置限制使用file-loader 进行处理,没有则转换成base64、从而减少代码的体积
配置:
{ test: [/\.(jpg|jpeg|png|svg|bmp)$/, /\.(eot|woff2?|ttf|svg)$/], loader: require.resolve("url-loader"), options: { name: "[path][name].[ext]", // name默认是加上hash值。这里做了更改,不让加 outputPath: "images", limit: 10240, // url-loader处理图片默认是转成base64, 这里配置如果小于10kb转base64,否则使用file-loader打包到images文件夹下 }, }
progress-bar-webpack-plugin:打包进度条插件
- const ProgressBarPlugin = require("progress-bar-webpack-plugin");
- new ProgressBarPlugin(),
webpackbar: 进度条插件(推荐 这个比较美观)
- const WebpackBar = require('webpackbar');
- new WebpackBar({
- color: "#85d", // 默认green,进度条颜色支持HEX
- basic: false, // 默认true,启用一个简单的日志报告器
- profile: false, // 默认false,启用探查器。
- }),
clean-webpack-plugin :清除打包后的文件 参考
其实 执行script 打包命令的时候 先执行 rimraf ./dist 效果是一样的
html-webpack-plugin:
- 为html文件中引入的外部资源如
script
、link
动态添加每次compile后的hash,防止引用缓存的外部文件问题- 可以生成创建html入口文件,比如单页面可以生成一个html文件入口,配置N个
html-webpack-plugin
可以生成N个页面入口- html-webpack-plugin配置
- 生成多页面配置
{ entry: 'index.js', output: { path: __dirname + '/dist', filename: 'index_bundle.js' }, plugins: [ new HtmlWebpackPlugin(), // Generates default index.html new HtmlWebpackPlugin({ // Also generate a test.html filename: 'test.html', template: 'src/assets/test.html' }) ] }
mini-css-extract-plugin:css压缩插件 文档
webpack-dev-server: 本地服务器 官方文档
配置信息
- {
- devServer: {
- contentBase: resolve('./'), // 对外提供的访问内容的路径,只有在提供静态文件访问的情况下才需要使用该配置。
- compress: true, // 配置是否启用 gzip 压缩。boolean 为类型,默认为 false。
- host: 'localhost' || baseDevServer.host,
- inline: true, // 切换dev-server的两种模式,默认情况server使用inline mode(live reload及构建信息的相关代码会被插入到bundle中。)。
- // false:切换到iframe mode(使用iframe mode会在通知栏下方显示构建信息)
- port: baseDevServer.port || 9000,
- quiet: true, // 当启用该配置,除了初始化信息会被写到console中,其他任何信息都不会被写进去。
- // errors和warnings也不会被写到console中。
- useLocalIp: baseDevServer.useLocalIp || false,
- overlay: { // 在编译过程中有任何错误,可以显示在网页上,在浏览器上全屏显示编译的errors或warnings。默认是关闭的
- warnings: false,
- errors: true
- },
- headers: { // 向所有的请求添加headers
- "X-Custom-Foo": "bar"
- },
- historyApiFallback: true, // 当使用html5 history api,将会在响应404时返回index.html。
- historyApiFallback: {
- rewrites: [ // 通过传递一个object来对该共呢个做更多的定
- { from: /^\/$/, to: '/views/landing.html' },
- { from: /^\/subpage/, to: '/views/subpage.html' },
- { from: /./, to: '/views/404.html' }
- ],
- disableDotRule: true // 当在路径中使用.符号,需要使用disableDotRule配置。
- },
- https: true, // 默认情况下dev-server使用http协议,通过配置可以支持https
- https: {
- key: fs.readFileSync("/path/to/server.key"),
- cert: fs.readFileSync("/path/to/server.crt"),
- ca: fs.readFileSync("/path/to/ca.pem"),
- },
- open: false, // 第一次构建是否自动用浏览器打开网页,默认是true
- openPage: '/different/page', // 配置项用于打开指定 URL 的网页
- hot: true, // 开启热更新HMR,只能跟新css。js和图片需要手动更新
- hotOnly: true, 启用HMR,当编译失败时,不刷新页面。
- proxy: {
- '/api': {
- target: 'https://api.github.com', // 代理地址
- pathRewrite: {
- '^/api': ''
- },
- // 默认代理服务器,会以我们实际在浏览器请求的主机名【localhost:8080】,作为代理服务器的主机名,
- // 然后代理服务器会带上这个主机名,去请求github,然而 github是不认识 【localhost:8080】
- // changeOrigin: true 就是以实际代理请求发生过程中的主机名去请求,如:代理服务器的主机名
- changeOrigin: true
- }
- }
- }
- }
Webpack.HotModuleReplacementPlugin :内容替换插件(本地环境)
loader-utils: GitHub - webpack/loader-utils: utils for webpack loaders
const loaderUtils = require('loader-utils');
文本替换loader
- const loaderUtils = require('loader-utils');
-
- module.exports = function (source) {
- const options = loaderUtils.getOptions(this);
- let result = source;
- if (options.arr) {
- options.arr.map(op => {
- result = result.replace(op.replaceFrom, op.replaceTo);
- })
- } else {
- result = source.replace(options.replaceFrom, options.replaceTo);
- }
- return result
-
- };
webpack.common.config.js
webpack.prod.config.js
webpack.dev.config.js
webpack 打包momentjs时会把所有语言包都打包,这样会使打包文件很大。此插件可以帮助我们只打包需要的语言包,大大减小打包文件大小。
- new Webpack.ContextReplacementPlugin(
- /moment[/\\]locale$/,
- /zh-cn/,
- ),
DepReporter 依赖收集自定义插件
HtmlJsToES5Plugin 将html中的script进行babel转为es5的插件
- const babel = require('@babel/core');
- const HtmlWebpackPlugin = require("html-webpack-plugin");
-
- class HtmlJsToES5Plugin {
- process(htmlPluginData) {
- return new Promise(function (resolve) {
- const scriptRegExp = /<script>[\s\S]*?<\/script>/gis;
- htmlPluginData.html = htmlPluginData.html.replace(scriptRegExp, function (match) {
- const code = match.replace("<script>", "").replace("</script>", "");
- const es5Code = babel.transform(code, { 'presets': ['@babel/preset-env'] }).code;
- return `<script>${es5Code}</script>`;
- });
- resolve();
- });
- }
-
-
- apply(compiler){
- compiler.hooks.compilation.tap('HtmlJsToES5Plugin', (compilation) => {
- HtmlWebpackPlugin.getHooks(compilation).afterTemplateExecution.tapAsync(
- "HtmlJsToES5Plugin",
- async (html, cb) => {
- await this.process(html);
- cb(null, html);
- }
- );
- });
- }
- }
-
- // exports.default = HtmlJsToES5Plugin;
- module.exports = HtmlJsToES5Plugin;
GitToHtmlPlugin: 将git信息存储插件
4、ScriptExtHtmlWebpackPlugin: 向标签添加额外属性数据、可将async
、defer
或module
属性添加到<script>
元素中,甚至可以将它们内联。
感觉是HtmlWebpackPlugin的增强
https://github.com/numical/script-ext-html-webpack-plugin
- const ScriptExtHtmlWebpackPlugin = require("script-ext-html-webpack-plugin");
- new ScriptExtHtmlWebpackPlugin({
- custom: {
- test: /\.js$/,
- attribute: 'crossorigin',
- value: 'anonymous'
- }
- }),
new Webpack.IgnorePlugin(/[\\/]mock[\\/]/),
TerserPlugin 压缩js
- // 替换的js压缩 因为uglifyjs不支持es6语法,
- new TerserPlugin({
- cache: true,
- sourceMap: isProd,
- extractComments: false, // 提取注释
- parallel: true, // 多线程
- terserOptions: {
- compress: {
- pure_funcs: ["console.log"],
- },
- },
- }),
OptimizeCSSAssetsPlugin 压缩css
- const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
- // 压缩css
- new OptimizeCSSAssetsPlugin({
- assetNameRegExp: /\.css$/g,
- cssProcessor: require("cssnano"),
- cssProcessorPluginOptions: {
- preset: ["default", { discardComments: { removeAll: true } }],
- },
- canPrint: true,
- }),
1、webpack和webpack-cli的安装 安装 | webpack 中文文档webpack 是一个模块打包器。它的主要目标是将 JavaScript 文件打包在一起,打包后的文件用于在浏览器中使用,但它也能够胜任转换(transform)、打包(bundle)或包裹(package)任何资源(resource or asset)。https://webpack.docschina.org/guides/installation
yarn add webpack-cli webpack --dev
npm webpack init
3、目录配置
- "scripts": {
- "test": "echo \"Error: no test specified\" && exit 1",
- "build": "webpack --mode=production --node-env=production --config ./config/webpack.config.js",
- "build:dev": "webpack --mode=development --config ./config/webpack.config.js",
- "build:prod": "webpack --mode=production --node-env=production --config ./config/webpack.config.js",
- "watch": "webpack --watch",
- "serve": "webpack serve --config ./config/webpack.config.js"
- }
- {
- test: /\.(js|jsx)$/i,
- loader: 'babel-loader',
- exclude: [path.resolve("node_modules")],
- options: {
- "presets": ["@babel/preset-env", "@babel/preset-react"],
- "plugins": ["@babel/plugin-syntax-dynamic-import", "@babel/plugin-transform-runtime"]
- }
- },
- resolve: {
- extensions: ['.js', '.jsx', '.json'],
- },
webpack5:postcss-px2rem-exclude
webpack5:
const cssRegLoader = [ stylesHandler, 'css-loader', { loader: "postcss-loader", options: { postcssOptions: { plugins: [ [ "autoprefixer", { overrideBrowserslist: ["> 1%", "last 2 versions", "not ie <= 8"], } ], require("postcss-plugin-px2rem")({ rootValue: 100, //换算基数, 默认100 ,这样的话把根标签的字体规定为1rem为50px,这样可以从设计稿上量出多少个px直接在代码中写多上px了。 // unitPrecision: 5, //允许REM单位增长到的十进制数字。 //propWhiteList: [], //默认值是一个空数组,这意味着禁用白名单并启用所有属性。 // propBlackList: [], //黑名单 exclude: /(node_module)/, //默认false,可以(reg)利用正则表达式排除某些文件夹的方法,例如/(node_module)/ 。如果想把前端UI框架内的px也转换成rem,请把此属性设为默认值 // selectorBlackList: [], //要忽略并保留为px的选择器 // ignoreIdentifier: false, //(boolean/string)忽略单个属性的方法,启用ignoreidentifier后,replace将自动设置为true。 // replace: true, // (布尔值)替换包含REM的规则,而不是添加回退。 // mediaQuery: false, //(布尔值)允许在媒体查询中转换px。 // minPixelValue: 3, //设置要替换的最小像素值(3px会被转rem)。 默认 0 }) ] } } }, "less-loader" ]webpack4:
{ loader: "postcss-loader", options: { sourceMap: isProd, plugins: [ require("autoprefixer")({ overrideBrowserslist: ["> 1%", "last 2 versions", "not ie <= 8"], }), require("postcss-px2rem-exclude")({ remUnit: 100, // 注意算法,这是750设计稿,html的font-size按照750比例 exclude: /node_modules/i, }) ], }, },
webpack5
optimization: { minimize: isProduction, minimizer: [ new TerserPlugin({ terserOptions: { compress: { drop_console: true, pure_funcs: ["console.info"], } }, // 注释剥离 extractComments: "all", }) ], }webpack4
optimization: { minimize: isProd, minimizer: [ // 替换的js压缩 因为uglifyjs不支持es6语法, new TerserPlugin({ cache: true, sourceMap: isProd, extractComments: false, // 提取注释 parallel: true, // 多线程 terserOptions: { compress: { pure_funcs: ["console.log"], }, }, }), ], },
process.cwd() :是当前Node.js进程执行时的文件夹地址——工作目录,保证了文件在不同的目录下执行时,路径始终不变
__dirname :是被执行的js 文件的地址 ——文件所在目录path.resolve :返回绝对路径
path.join :方法使用平台特定的分隔符把全部给定的 path 片段连接到一起,并规范化生成的路径。
publicPath: webpack中publicPath的深入解析
resolveLoader:【webpack】中resolveLoader的使用方法 - 前端精髓 - 博客园
require.resolve:node的路径解析require.resolve
loc: loc - npm
const loc_1 = require("loc"); const { num: numOfProject } = await loc_1.scan('src', { extNames: ['js', 'jsx'] }); console.log('组件代码行数:', numOfComponents); console.log('项目代码行数:', numOfProject);
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。