当前位置:   article > 正文

如何使用webpack搭建项目

webpack搭建

如何使用webpack搭建项目

一、什么是loader

单一原则,一个loader只做一件事

多个loader,从右到左,从下到上开始解析

二、使用到的loader

样式相关的loader

1、less-loader

自动将less转换为CSS

2、postcss-loader

一、什么是postcss

        postCSSsass/less不同, 它不是CSS预处理器、postCSS是一款使用插件去转换CSS的工具。

二、使用到的插件

autoprefixer: 自动添加浏览器样式前缀

  1. require("autoprefixer")({
  2. "overrideBrowserslist": [
  3. "ie >= 8", // 兼容IE7以上浏览器
  4. "Firefox >= 3.5", // 兼容火狐版本号大于3.5浏览器
  5. "chrome >= 35", // 兼容谷歌版本号大于35浏览器,
  6. "opera >= 11.5", // 兼容欧朋版本号大于11.5浏览器
  7. ]
  8. })

postcss-px2rem-exclude: 自动把px代为转换成rem

原插件为(postcss-px2rem 该插件支持排除文件)

  1. require("postcss-px2rem-exclude")({
  2. remUnit: 100, // 注意算法,这是750设计稿,html的font-size按照750比例
  3. exclude: /node_modules/i,
  4. })

3、css-loader

css-loader 会对 @import 和 url() 进行处理,就像 js 解析 import/require() 一样。

4、MiniCssExtractPlugin.loader

MiniCssExtractPlugin.loader mini-css-extract-plugin插件快速入门

作用:从css文件中提取css代码到单独的文件中,对css代码进行代码压缩等

配置:

  1. {
  2. loader: MiniCssExtractPlugin.loader,
  3. options: {
  4. // 这里可以指定一个 publicPath
  5. // 默认使用 webpackOptions.output中的publicPath
  6. // publicPath的配置,和plugins中设置的filename和chunkFilename的名字有关
  7. // 如果打包后,background属性中的图片显示不出来,请检查publicPath的配置是否有误
  8. publicPath: './',
  9. // publicPath: devMode ? './' : '../', // 根据不同环境指定不同的publicPath
  10. hmr: devMode, // 仅dev环境启用HMR功能
  11. }
  12. }

5、style-loader

style-loader 的功能就一个,在 DOM 里插入一个 <style> 标签,并且将 CSS 写入这个标签内。

js相关的loader

babel-loader

babel官网

什么是babel:Babel 是一个 JavaScript 编译器,它是一个工具链,主要的用途就是在旧的浏览器或环境中将ECMAScript 2015+ 代码转换为向后兼容的 js 代码。

预设和插件:babel转换代码的依据

presets:执行的转换顺序是从下到上,从右到左

@babel/preset-env :   用于编译 ES2015+ 语法

@babel/preset-react  :  用于 React

配置:

  1. {
  2. test: /\.(js|jsx)$/,
  3. loader: require.resolve("babel-loader"),
  4. exclude: [path.resolve("node_modules")],
  5. options: {
  6. presets: [
  7. require("@babel/preset-env").default,
  8. require("@babel/preset-react").default
  9. ],
  10. plugins: [
  11. // 装饰器插件
  12. ["@babel/plugin-proposal-decorators", { "legacy": true }],
  13. ["@babel/plugin-proposal-class-properties", { "loose": false }],
  14. // babel运行时
  15. require("@babel/plugin-transform-runtime").default,
  16. ],
  17. sourceType: 'unambiguous'
  18. },
  19. }

@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;

url-loader

处理js之外的资源文件,如图片 字体等

url-loader 可以识别图片的大小,超过配置限制使用file-loader 进行处理,没有则转换成base64、从而减少代码的体积

配置:

  1. {
  2. test: [/\.(jpg|jpeg|png|svg|bmp)$/, /\.(eot|woff2?|ttf|svg)$/],
  3. loader: require.resolve("url-loader"),
  4. options: {
  5. name: "[path][name].[ext]", // name默认是加上hash值。这里做了更改,不让加
  6. outputPath: "images",
  7. limit: 10240, // url-loader处理图片默认是转成base64, 这里配置如果小于10kb转base64,否则使用file-loader打包到images文件夹下
  8. },
  9. }

三、使用到的插件

progress-bar-webpack-plugin:打包进度条插件

  1. const ProgressBarPlugin = require("progress-bar-webpack-plugin");
  2. new ProgressBarPlugin(),

webpackbar: 进度条插件(推荐 这个比较美观)

  1. const WebpackBar = require('webpackbar');
  2. new WebpackBar({
  3. color: "#85d", // 默认green,进度条颜色支持HEX
  4. basic: false, // 默认true,启用一个简单的日志报告器
  5. profile: false, // 默认false,启用探查器。
  6. }),

clean-webpack-plugin :清除打包后的文件 参考

在这里插入图片描述

 其实 执行script 打包命令的时候 先执行 rimraf ./dist 效果是一样的

html-webpack-plugin:

  • 为html文件中引入的外部资源如scriptlink动态添加每次compile后的hash,防止引用缓存的外部文件问题
  • 可以生成创建html入口文件,比如单页面可以生成一个html文件入口,配置Nhtml-webpack-plugin可以生成N个页面入口
  • html-webpack-plugin配置
  • 生成多页面配置
  1. {
  2. entry: 'index.js',
  3. output: {
  4. path: __dirname + '/dist',
  5. filename: 'index_bundle.js'
  6. },
  7. plugins: [
  8. new HtmlWebpackPlugin(), // Generates default index.html
  9. new HtmlWebpackPlugin({ // Also generate a test.html
  10. filename: 'test.html',
  11. template: 'src/assets/test.html'
  12. })
  13. ]
  14. }

mini-css-extract-plugin:css压缩插件  文档

webpack-dev-server: 本地服务器  官方文档

配置信息 

  1. {
  2. devServer: {
  3. contentBase: resolve('./'), // 对外提供的访问内容的路径,只有在提供静态文件访问的情况下才需要使用该配置。
  4. compress: true, // 配置是否启用 gzip 压缩。boolean 为类型,默认为 false。
  5. host: 'localhost' || baseDevServer.host,
  6. inline: true, // 切换dev-server的两种模式,默认情况server使用inline mode(live reload及构建信息的相关代码会被插入到bundle中。)。
  7. // false:切换到iframe mode(使用iframe mode会在通知栏下方显示构建信息)
  8. port: baseDevServer.port || 9000,
  9. quiet: true, // 当启用该配置,除了初始化信息会被写到console中,其他任何信息都不会被写进去。
  10. // errors和warnings也不会被写到console中。
  11. useLocalIp: baseDevServer.useLocalIp || false,
  12. overlay: { // 在编译过程中有任何错误,可以显示在网页上,在浏览器上全屏显示编译的errors或warnings。默认是关闭的
  13. warnings: false,
  14. errors: true
  15. },
  16. headers: { // 向所有的请求添加headers
  17. "X-Custom-Foo": "bar"
  18. },
  19. historyApiFallback: true, // 当使用html5 history api,将会在响应404时返回index.html。
  20. historyApiFallback: {
  21. rewrites: [ // 通过传递一个object来对该共呢个做更多的定
  22. { from: /^\/$/, to: '/views/landing.html' },
  23. { from: /^\/subpage/, to: '/views/subpage.html' },
  24. { from: /./, to: '/views/404.html' }
  25. ],
  26. disableDotRule: true // 当在路径中使用.符号,需要使用disableDotRule配置。
  27. },
  28. https: true, // 默认情况下dev-server使用http协议,通过配置可以支持https
  29. https: {
  30. key: fs.readFileSync("/path/to/server.key"),
  31. cert: fs.readFileSync("/path/to/server.crt"),
  32. ca: fs.readFileSync("/path/to/ca.pem"),
  33. },
  34. open: false, // 第一次构建是否自动用浏览器打开网页,默认是true
  35. openPage: '/different/page', // 配置项用于打开指定 URL 的网页
  36. hot: true, // 开启热更新HMR,只能跟新css。js和图片需要手动更新
  37. hotOnly: true, 启用HMR,当编译失败时,不刷新页面。
  38. proxy: {
  39. '/api': {
  40. target: 'https://api.github.com', // 代理地址
  41. pathRewrite: {
  42. '^/api': ''
  43. },
  44. // 默认代理服务器,会以我们实际在浏览器请求的主机名【localhost:8080】,作为代理服务器的主机名,
  45. // 然后代理服务器会带上这个主机名,去请求github,然而 github是不认识 【localhost:8080】
  46. // changeOrigin: true 就是以实际代理请求发生过程中的主机名去请求,如:代理服务器的主机名
  47. changeOrigin: true
  48. }
  49. }
  50. }
  51. }

Webpack.HotModuleReplacementPlugin  :内容替换插件(本地环境)

四、实现一个loader

loader-utils: GitHub - webpack/loader-utils: utils for webpack loaders

const loaderUtils = require('loader-utils');

文本替换loader

  1. const loaderUtils = require('loader-utils');
  2. module.exports = function (source) {
  3. const options = loaderUtils.getOptions(this);
  4. let result = source;
  5. if (options.arr) {
  6. options.arr.map(op => {
  7. result = result.replace(op.replaceFrom, op.replaceTo);
  8. })
  9. } else {
  10. result = source.replace(options.replaceFrom, options.replaceTo);
  11. }
  12. return result
  13. };

五、多环境配置

webpack.common.config.js

webpack.prod.config.js

webpack.dev.config.js

六、prod使用的插件

1、内容替换插件: new Webpack.ContextReplacementPlugin

webpack 打包momentjs时会把所有语言包都打包,这样会使打包文件很大。此插件可以帮助我们只打包需要的语言包,大大减小打包文件大小。

  1. new Webpack.ContextReplacementPlugin(
  2. /moment[/\\]locale$/,
  3. /zh-cn/,
  4. ),

2、自定义插件

DepReporter 依赖收集自定义插件

HtmlJsToES5Plugin 将html中的script进行babel转为es5的插件

  1. const babel = require('@babel/core');
  2. const HtmlWebpackPlugin = require("html-webpack-plugin");
  3. class HtmlJsToES5Plugin {
  4. process(htmlPluginData) {
  5. return new Promise(function (resolve) {
  6. const scriptRegExp = /<script>[\s\S]*?<\/script>/gis;
  7. htmlPluginData.html = htmlPluginData.html.replace(scriptRegExp, function (match) {
  8. const code = match.replace("<script>", "").replace("</script>", "");
  9. const es5Code = babel.transform(code, { 'presets': ['@babel/preset-env'] }).code;
  10. return `<script>${es5Code}</script>`;
  11. });
  12. resolve();
  13. });
  14. }
  15. apply(compiler){
  16. compiler.hooks.compilation.tap('HtmlJsToES5Plugin', (compilation) => {
  17. HtmlWebpackPlugin.getHooks(compilation).afterTemplateExecution.tapAsync(
  18. "HtmlJsToES5Plugin",
  19. async (html, cb) => {
  20. await this.process(html);
  21. cb(null, html);
  22. }
  23. );
  24. });
  25. }
  26. }
  27. // exports.default = HtmlJsToES5Plugin;
  28. module.exports = HtmlJsToES5Plugin;

GitToHtmlPlugin: 将git信息存储插件

4、ScriptExtHtmlWebpackPlugin: 向标签添加额外属性数据、可将asyncdefermodule属性添加到<script>元素中,甚至可以将它们内联。

感觉是HtmlWebpackPlugin的增强

https://github.com/numical/script-ext-html-webpack-plugin

  1. const ScriptExtHtmlWebpackPlugin = require("script-ext-html-webpack-plugin");
  2. new ScriptExtHtmlWebpackPlugin({
  3. custom: {
  4. test: /\.js$/,
  5. attribute: 'crossorigin',
  6. value: 'anonymous'
  7. }
  8. }),

5、Webpack.IgnorePlugin 内容忽略插件

new Webpack.IgnorePlugin(/[\\/]mock[\\/]/),

七、压缩插件

TerserPlugin 压缩js

  1. // 替换的js压缩 因为uglifyjs不支持es6语法,
  2. new TerserPlugin({
  3. cache: true,
  4. sourceMap: isProd,
  5. extractComments: false, // 提取注释
  6. parallel: true, // 多线程
  7. terserOptions: {
  8. compress: {
  9. pure_funcs: ["console.log"],
  10. },
  11. },
  12. }),

OptimizeCSSAssetsPlugin  压缩css

  1. const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
  2. // 压缩css
  3. new OptimizeCSSAssetsPlugin({
  4. assetNameRegExp: /\.css$/g,
  5. cssProcessor: require("cssnano"),
  6. cssProcessorPluginOptions: {
  7. preset: ["default", { discardComments: { removeAll: true } }],
  8. },
  9. canPrint: true,
  10. }),

七、从零开始搭建一个webpack5项目

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 

2、初始化项目 命令行接口(CLI) | webpack 中文文档webpack 是一个模块打包器。它的主要目标是将 JavaScript 文件打包在一起,打包后的文件用于在浏览器中使用,但它也能够胜任转换(transform)、打包(bundle)或包裹(package)任何资源(resource or asset)。https://webpack.docschina.org/api/cli/#init

3、目录配置

  1. 新建config目录
  2. 移动webpack.config.js到config目录
  3. 修改package.json中scripts命令
  1. "scripts": {
  2. "test": "echo \"Error: no test specified\" && exit 1",
  3. "build": "webpack --mode=production --node-env=production --config ./config/webpack.config.js",
  4. "build:dev": "webpack --mode=development --config ./config/webpack.config.js",
  5. "build:prod": "webpack --mode=production --node-env=production --config ./config/webpack.config.js",
  6. "watch": "webpack --watch",
  7. "serve": "webpack serve --config ./config/webpack.config.js"
  8. }

4、配置babel 这里遇到了一个坑(一直报错)==>(加上exclude选项排除node_modules选项后不报错)

  1. {
  2. test: /\.(js|jsx)$/i,
  3. loader: 'babel-loader',
  4. exclude: [path.resolve("node_modules")],
  5. options: {
  6. "presets": ["@babel/preset-env", "@babel/preset-react"],
  7. "plugins": ["@babel/plugin-syntax-dynamic-import", "@babel/plugin-transform-runtime"]
  8. }
  9. },

5、配置reslove选项

resolve.extensions 注意如果不配置该选项 会导致import导入的时候需要写全称

  1. resolve: {
  2. extensions: ['.js', '.jsx', '.json'],
  3. },

解析(Resolve) | webpack 中文文档webpack 是一个模块打包器。它的主要目标是将 JavaScript 文件打包在一起,打包后的文件用于在浏览器中使用,但它也能够胜任转换(transform)、打包(bundle)或包裹(package)任何资源(resource or asset)。https://webpack.docschina.org/configuration/resolve/#resolveextensions

6、postcss-loader 的 px转rem插件

webpack5:postcss-px2rem-exclude

  1. postcss-px2rem-exclude 插件不支持webpack5 
  2. webpack5 需要使用另外的插件 postcss-px2rem-exclude
  3. 配合使用rem.js进行页面适配
  4. rem.js - npm

webpack5:

  1. const cssRegLoader = [
  2. stylesHandler,
  3. 'css-loader',
  4. {
  5. loader: "postcss-loader",
  6. options: {
  7. postcssOptions: {
  8. plugins: [
  9. [
  10. "autoprefixer", {
  11. overrideBrowserslist: ["> 1%", "last 2 versions", "not ie <= 8"],
  12. }
  13. ],
  14. require("postcss-plugin-px2rem")({
  15. rootValue: 100, //换算基数, 默认100 ,这样的话把根标签的字体规定为1rem为50px,这样可以从设计稿上量出多少个px直接在代码中写多上px了。
  16. // unitPrecision: 5, //允许REM单位增长到的十进制数字。
  17. //propWhiteList: [], //默认值是一个空数组,这意味着禁用白名单并启用所有属性。
  18. // propBlackList: [], //黑名单
  19. exclude: /(node_module)/, //默认false,可以(reg)利用正则表达式排除某些文件夹的方法,例如/(node_module)/ 。如果想把前端UI框架内的px也转换成rem,请把此属性设为默认值
  20. // selectorBlackList: [], //要忽略并保留为px的选择器
  21. // ignoreIdentifier: false, //(boolean/string)忽略单个属性的方法,启用ignoreidentifier后,replace将自动设置为true。
  22. // replace: true, // (布尔值)替换包含REM的规则,而不是添加回退。
  23. // mediaQuery: false, //(布尔值)允许在媒体查询中转换px。
  24. // minPixelValue: 3, //设置要替换的最小像素值(3px会被转rem)。 默认 0
  25. })
  26. ]
  27. }
  28. }
  29. },
  30. "less-loader"
  31. ]

webpack4:

  1. {
  2. loader: "postcss-loader",
  3. options: {
  4. sourceMap: isProd,
  5. plugins: [
  6. require("autoprefixer")({
  7. overrideBrowserslist: ["> 1%", "last 2 versions", "not ie <= 8"],
  8. }),
  9. require("postcss-px2rem-exclude")({
  10. remUnit: 100, // 注意算法,这是750设计稿,html的font-size按照750比例
  11. exclude: /node_modules/i,
  12. })
  13. ],
  14. },
  15. },

7、配置js压缩

webpack5

  1. optimization: {
  2. minimize: isProduction,
  3. minimizer: [
  4. new TerserPlugin({
  5. terserOptions: {
  6. compress: {
  7. drop_console: true,
  8. pure_funcs: ["console.info"],
  9. }
  10. },
  11. // 注释剥离
  12. extractComments: "all",
  13. })
  14. ],
  15. }

webpack4

  1. optimization: {
  2. minimize: isProd,
  3. minimizer: [
  4. // 替换的js压缩 因为uglifyjs不支持es6语法,
  5. new TerserPlugin({
  6. cache: true,
  7. sourceMap: isProd,
  8. extractComments: false, // 提取注释
  9. parallel: true, // 多线程
  10. terserOptions: {
  11. compress: {
  12. pure_funcs: ["console.log"],
  13. },
  14. },
  15. }),
  16. ],
  17. },

知识扩展

process.cwd() :是当前Node.js进程执行时的文件夹地址——工作目录,保证了文件在不同的目录下执行时,路径始终不变
__dirname :是被执行的js 文件的地址 ——文件所在目录

path.resolve :返回绝对路径

path.join  :方法使用平台特定的分隔符把全部给定的 path 片段连接到一起,并规范化生成的路径。

publicPathwebpack中publicPath的深入解析

resolveLoader:【webpack】中resolveLoader的使用方法 - 前端精髓 - 博客园

require.resolve:node的路径解析require.resolve 

locloc - npm

  1. const loc_1 = require("loc");
  2. const { num: numOfProject } = await loc_1.scan('src', { extNames: ['js', 'jsx'] });
  3. console.log('组件代码行数:', numOfComponents);
  4. console.log('项目代码行数:', numOfProject);
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/997732
推荐阅读
  

闽ICP备14008679号