web兼容性问题解决方案

340 阅读11分钟

image-20231109104529526

原因:

react16.8 之后框架不支持ie兼容 js不兼容 还会有语法不兼容的情况 没报错说明是框架本身的问题 不是部分语法的问题

开发兼容性问题

1 浏览器内核: 兼容IE

适配移动端:

<!DOCTYPE html>
<meta
        name="viewport"
        content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0"
/>
<body>
<div class="title">模板</div>
</body>
<script>
</script>
<style>
</style>

2 屏幕兼容性 css @media

使用 @media 查询,你可以针对不同的媒体类型定义不同的样式。

@media 可以针对不同的屏幕尺寸设置不同的样式

比如根据不同屏幕调整字号

3 手机端兼容

一、基于ADK的JAVA编程

目前企业对Android app开发使用的主流语言是Java。Java语言最大的特点就是提高了软件交互的可能性。

可以说Android手机的应用几乎都是用Java语言写的。使用Java语言开发的软件库、数据库和运行时是android手机软件的一个主要特点。

Java有很多优势,所以android应用软件的开发应用了Java核心类的知识,这也让Java语言开发的安卓软件有很大的优势。

虽然使用Java开发应用程序方便,但是容易降低应用程序的质量。Android虽然用虚拟机运行Java,比非智能的平台JVM更有效,但始终比不上NDK,所以安卓app运行非常慢,主要是因为Java有内存回收机制。

因此开发人员经常使用Java开发应用程序而不必关注控制内存泄漏问题(特别是一些小软件)。当进程超过虚拟机分配的阈值时,它们将被系统杀掉以释放内存。这可能导致app崩溃,假死等情况。

二、基于NDK的C语言编程

C语言是一种结构化语言。它层次结构清晰,易于模块化排列,易于调试和保护。C语言有很强的处理能力。

它不仅运算符和数据类型丰富,而且容易完成各种复杂的数据结构。它也是最流行的编程语言之一。

C语言功能丰富,应用广泛,兼具高级语言和低级语言的特点。适合作为系统渲染语言,可以用来编译系统软件和应用程序软件。

三、基于JVM的新的编程语言

Kotlin是一种基于JVM的新的编程语言,由JetBrains 开发编写。JetBrains作为JavaIDE IntelliJ的热门提供商,已经在Apache的许可下开放了其Kotlin编程语言。

与Java相比,Kotlin的语法更加简洁和富有表现力,并提供了更多的功能,例如高阶函数、运算符重载和字符串模板。它与Java具有很高的互操作性,可以同时用于一个项目。

尝试1 html配置

html添加:不好使

<meta http-equiv="X-UA-Compatible" content="IE=edge"/>

尝试2 修改已有webpack配置

craco.config.ts webpack添加配置

 alias: {
          'react': path.resolve('./node_modules/react'),
          'react-dom': path.resolve('./node_modules/react-dom'),
        },

尝试3 browserslist

官网: browsersl.ist/

位置: package.json配置或者单独文件都可

实现功能: 设置兼容浏览器支持

能兼容node版本 ios 各种版本 近两年 哪年开始等等以及not 兼容哪些

注意`: webpack配置 proset target会覆盖browserlist 尽量不要在这配 仅js生效

命令查询

npx browserslist
npx browserslist ">1%,last 2 years"

是或的关系

chrome 79兼容的话 chrome8也兼容 但是市场占有率低 所以没列出来

   "browserslist": {
    "production": [
      ">0.2%",// 市场占有率 eg >5% in US
      "last 2 version", //最新两个版本
      "not dead",// 24个月之内都没有官网更新 不再兼容 
      "Firefox ESR",// 专为一些学校提供的内核
      "ie > 9"    
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version",
      "ie > 9"    
    ]
  },

image-20231026205151404

工程化

caniuse.com/

webpack

exclude: /node module/

bundle.js

entry 第三方库

usebuiltlns

webpack

webpack.docschina.org/concepts/

尝试4 polyfill

最后一招: 安装polyfill 兼容性工具解决

package.json

postcss

babel

babel7之前

"presets":["stage-0"]

尝试5 webpack+babel

优秀博客

betheme.net/houduan/156…

entry:入口 指明了需要打包文件的入口,让webpack知道从按个文件开始打包 output: 输出 指明了打包的文件要输出到哪里去,并且如何命名等 loader:加载器 由于webpack本省的功能很少,只能解析js、json等资源,所以在处于其他资源的时候就需要借助loader,webpack才能解析 plugins:插件 就好比浏览器的插件一样,可以扩展webpack的功能,我们需要下载并且引用它 mode:模式 生产模式:production 开发模式:deveplopment

webpack

官网: webpack.docschina.org/concepts/

1 安装webpack

安装webpack和cli

webpack -cli 命令行

webpack 代码中

conflict peer dependency or retry this command with

这个问题时因为npm的v7以后的版本都默认安装了peerDependency,它虽然解决了依赖安装的冗余的问题,但有时也会导致依赖的包版本与各个子项目依赖的包版本相互不兼容,所以安装时要加上--legacy-peer-deps

image-20231031153730356

2

image-20231031161901049

2 .webpack文件备份1

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
​
module.exports = {
  entry: './src/index.tsx',
  output: {
    path: path.resolve(__dirname, 'build'),
    filename: 'bundle.js',
  },
  resolve: {
    extensions: ['.js', '.jsx', '.ts', '.tsx'],
    alias: {
        app: path.resolve(__dirname, 'src/app'), // 适应你的项目结构
        services: path.resolve(__dirname, 'src/services'), // 适应你的项目结构
        routes: path.resolve(__dirname, 'src/routes'), // 适应你的项目结构
        layout:path.resolve(__dirname, 'src/layout'),
        features:path.resolve(__dirname, 'src/features'),
        components:path.resolve(__dirname, 'src/components'),
        pages: path.resolve(__dirname, 'src/pages'), // 适应你的项目结构
        context: path.resolve(__dirname, 'src/context'), // 适应你的项目结构
        assets:  path.resolve(__dirname, 'src/assets'), // 适应你的项目结构
        utils: path.resolve(__dirname, 'src/utils'), // 适应你的项目结构
      }
  },
  
  module: {
    rules: [
      {
        test: /.(js|jsx|ts|tsx)$/,
        exclude: /node_modules/,
        use: 'babel-loader',
      },
      {
        test: /.module.scss$/,
        use: [
          MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader',
            options: {
              modules: true,
            },
          },
          'sass-loader',
        ],
      },
     
      {
        test: /.css$/,
        use: ['style-loader', 'css-loader'],
      },
      {
        test: /.s[ac]ss$/, // 匹配 .scss 或 .sass 文件
        use: [
          'style-loader', // 创建 <style> 标签并将样式插入其中
          'css-loader',   // 将 CSS 转换为 CommonJS 模块
          'sass-loader'   // 将 Sass 编译为 CSS
        ],
      },
     
      {
        test: /.(jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)$/,
        loader: 'file-loader',
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: 'public/index.html',
    }),
    new MiniCssExtractPlugin(),
  ],
  devServer: {
    contentBase: './build',
    port: 3000,
    historyApiFallback: true,
  },
};

3. 报错1 文件配置

img转存失败,建议直接上传图片文件

 {
        test: /.(jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)$/,
        loader: 'file-loader',
      },

报错2 sass loader

throw new Error("Module build failed (from ./node_modules/sass-loader/dist/cjs.js):\nexpected "{".\n ╷\n2 │ import API from "!../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js";\n │ ^\n ╵\n src\pages\videoZone\index.module.scss 2:101 root stylesheet");

image-20231109105155209

安装css loader命令

npm install sass-loader@latest
npm install node-sass@latest
npm cache clean --force
npm install
yarn add postcss-loader    
yarn add style-loader  
yarn add sass-loader
yarn add postcss-preset-env
webpack --config webpack.config.js

autoprefixer -D 自动添加浏览器前缀

 {
        test: /.css$/,
        use: [
            'style-loader', 'css-loader',
             {
                loader: 'postcss-loader',
                options:{
                    postcssOptions:{
                        plugins:"autoprefixer"
                    }
                }
            }
        ],
      },

postcss是一个功能 给postcss再添加插件

postcss-preset-env 预设 安装对应的插件,配置对应的插件

1 | throw new Error("Module build failed (from ./node_modules/sass-loader/dist/cjs.js):\nexpected "{".\n ╷\njectStylesIntoStyleTag.js";\n │

很多人在说版本不兼容的问题

4.打包css-loader 顺序 自定义解析

 {
        test: /.css$/,
        use: ['style-loader', 'css-loader','postcss-loader'],
      },
      
  完整写法 是对象 里面可以加options 从右向左读取 style-loader写在前面,在css基础上继续读取
   {
        test: /.css$/,
        use: [
          { loader: 'style-loader'}, 
          {
            loader: 'css-loader',
            options: {
              modules: true,
            },
          }
        ],
      },

less 报错 添加less

 {
        test: /.less$/,
        use: ['style-loader', 'css-loader','less-loader'],// 先less 再css 再style
 },

postcss插件 -postcssOptions-plugins

1 postcss是一个功能 给postcss再添加插件

{
        test: /.css$/,
        use: ['style-loader', 'css-loader','postcss-loader'],// postcss 在里面添加插件 自动添加浏览器前缀 css样式重置 
},

2 autoprefixer -D 自动添加浏览器前缀

 {
        test: /.css$/,
        use: [
            'style-loader',
            'css-loader',
             {
                loader: 'postcss-loader',
                options:{
                    postcssOptions:{ // 抽取从这里开始 规则是插件自己定义的 
                        plugins:"autoprefixer"
                    }
                }
            }
        ],
      },

3 postcss-loader可以单独抽取一个文件 postcss.config.js*=*> module.exports={plugins:"autoprefixer"}

postcss插件-postcss-preset-env 插件

1 预设 安装对应的插件,配置对应的插件 相当于内置autoprefixer

可以将现代css转化为大多数浏览器认识的css,并且根据目标浏览器或运行时环境添加所需的 polyfill

module.exports={plugins:"postcss-preset-env"}

2 将px转化为rem vw

=> webpack不是本身强大, 社区强大 插件很多

现代的前端开发模式,不需要手动添加浏览器前缀 比如umi

5. 打包资源文件--加载文件-内置

image-20231110094627679转存失败,建议直接上传图片文件

   
      {
        test: /.(jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)$/,
        // loader: 'file-loader',
        type: "asset"
      },
 {
        test: /.(jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)$/,
        // loader: 'file-loader',
        type: "asset/resource" // 发现生成图片,而且重命名 设置了新路径
        //  type: "asset/inline" // 将图片base64编码  直接放到js中
      },
    

性能:

inline高 优:少发送n个文件次http网络请求,缺点: js时间长

resource: 缺:多网络请求

合理规范: 对于小图片base64 编码,对于大图片单独url-设置

默认asset:自动

 {
        test: /.(jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)$/,
        // loader: 'file-loader',
        // 设置加载类型
        type: "asset",
        // 控制加载大小
        parser:{
          dataUrlCondition:{
          maxSize:60*1024
          }
        },
        // 重命名: 占位符 +8位hash+扩展符 
        generator:{
          // hash值 唯一
          filename:"[name]_[hash:8][ext]"
        }
      },

6. 打包js文件-babel-loader

es6不兼容ie8,只在ie10、ie11中兼容了部分es6的API;实现兼容的方法:可以利用“babel-loader”在ie8中把es6的代码编译成es5执行,使用“npm install babel-loader”即可安装

es6转es5

1 babel

 {
        test: /.(js|jsx|ts|tsx)$/,
        exclude: /node_modules/,
        use: 'babel-loader',
        options:{
          plugins:[
            // 箭头函数变function  不可能每个语法都用插件
            "@bable/plugin-transform-arrow-functions"
           ]
        }
      },

2 babel预设 常见三种预设

babel.config.js

module.exports={
        // plugins:[
        //   // 箭头函数变function  不可能每个语法都用插件
        //   "@bable/plugin-transform-arrow-functions"
        //  ]
        presets: [
            "@babel/preset-env",//es6
            "@babel/preset-react",
            "@babel/preset-typescript"
          ]      
}
   "build": "webpack --mode development",

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
​
module.exports = {
  entry: './src/index.tsx',
  output: {
    path: path.resolve(__dirname, 'build'),
    filename: 'bundle.js',
    publicPath :'/bbs/'
  },
  resolve: {
    extensions: ['.js', '.jsx', '.ts', '.tsx'],
    alias: {
        app: path.resolve(__dirname, 'src/app'), 
        services: path.resolve(__dirname, 'src/services'), 
        routes: path.resolve(__dirname, 'src/routes'), 
        layout:path.resolve(__dirname, 'src/layout'),
        features:path.resolve(__dirname, 'src/features'),
        components:path.resolve(__dirname, 'src/components'),
        pages: path.resolve(__dirname, 'src/pages'), 
        context: path.resolve(__dirname, 'src/context'), 
        assets:  path.resolve(__dirname, 'src/assets'), 
        utils: path.resolve(__dirname, 'src/utils'), 
      }
  },
  
  module: {
    rules: [
      {
        test: /.(js|jsx|ts|tsx)$/,
        exclude: /node_modules/,
        use: 'babel-loader'
      },
      {
        test: /.module.scss$/,
        use: [
          MiniCssExtractPlugin.loader,
          { loader: 'style-loader'},
          {
            loader: 'css-loader',
            options: {
              modules: true,
            },
          },
          'sass-loader',
        ],
      },
     
      {
        test: /.css$/,
        use: ['style-loader', 'css-loader',
        {
          loader: 'postcss-loader',
          options: {
            postcssOptions:{ // 抽取从这里开始 规则是插件自己定义的 
              plugins:"postcss-preset-env"
          }
          },
        },],
      },
      {
        test: /.s[c]ss$/, // 匹配 .scss 或 .sass 文件
        use: [
          'style-loader', // 创建 <style> 标签并将样式插入其中
          'css-loader',   // 将 CSS 转换为 CommonJS 模块
          'sass-loader'   // 将 Sass 编译为 CSS
        ],
      },
      {
        test: /.less$/, // 匹配 .scss 或 .sass 文件
        use: [
          'style-loader', // 创建 <style> 标签并将样式插入其中
          'css-loader',   // 将 CSS 转换为 CommonJS 模块
          'less-loader'   // 将 less 编译为 CSS
        ],
      },
     // 资源文件
      {
        test: /.(jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)$/,
        // loader: 'file-loader',
        // 设置加载类型
        type: "asset",
        // 控制加载大小
        parser:{
          dataUrlCondition:{
          maxSize:60*1024
          }
        },
        // 重命名: 占位符 +8位hash+扩展符 
        generator:{
          // hash值 唯一
          filename:"[name]_[hash:8][ext]"
        }
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: 'public/index.html',
    }),
    new MiniCssExtractPlugin(),
  ],
  devServer: {
    contentBase: './build',
    port: 3000,
    historyApiFallback: true,
  },
};

7. craco 直接改webpack

问题截图:

This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to: - add a fallback 'resolve.fallback: { "process": require.resolve("process/browser") }' - install 'process' If you don't want to include a polyfill, you can use an empty module like this: resolve.fallback: { "process": false } @ ./src/App.vue?vue&type=script&lang=js 1:0-189 1:0-189 1:190-368 1:190-368 @ ./src/App.vue 2:0-54 3:0-49 3:0-49 6:49-55 @ ./src/main.js 4:0-28 6:22-25

webpack compiled with 1 error 问题描述: 查了很多资料发现是因为webpack版本引起的,在webpack5中移除了nodejs核心模块的polyfill自动引入,具体可查看这篇文章

wenku.baidu.com/view/7b8427…

通过对日志的分析因为有其他组件引用到了 polyfills 的核心组件并没有安装,所以报错了,这里需要执行 npm install 命令进行包安装即可。

原因是由于在webpack5中移除了nodejs核心模块的polyfill自动引入,所以需要手动引入

解决方案: 1、运行下面这行指令,安装在 Webpack 中 Polyfill Node.js 核心模块。

npm install node-polyfill-webpack-plugin 2、在vue.config.json中添加(本文作者没有用到这一步,用第一步命令安装后就可以运行)

//头部引用 const NodePolyfillPlugin = require('node-polyfill-webpack-plugin')

//加入 configureWebpack: { plugins: [new NodePolyfillPlugin()] } 完整vue.config.json文件如下:

const NodePolyfillPlugin = require('node-polyfill-webpack-plugin')

module.exports = defineConfig({ configureWebpack: { plugins: [new NodePolyfillPlugin()] } })

8. 升级浏览器版本

9. antd版本兼容

ant-design.gitee.io/docs/react/…

Ant Design 支持最近 2 个版本的现代浏览器。如果你需要兼容旧版浏览器,请根据实际需求进行降级处理:

StyleProvider

查看 @ant-design/cssinjs.

注意版本对应 查看源码可以看到对应版本

image-20240122151952225

image-20240122152049335转存失败,建议直接上传图片文件

:where 选择器

Ant Design 的 CSS-in-JS 默认通过 :where 选择器降低 CSS Selector 优先级,以减少用户升级时额外调整自定义样式的成本,不过 :where 语法的兼容性在低版本浏览器比较差。在某些场景下你如果需要支持旧版浏览器(或与 TailwindCSS 优先级冲突),你可以使用 @ant-design/cssinjs 取消默认的降权操作(请注意版本保持与 antd 一致):

import { StyleProvider } from '@ant-design/cssinjs';
// `hashPriority` 默认为 `low`,配置为 `high` 后,// 会移除 `:where` 选择器封装export default () => (  <StyleProvider hashPriority="high">    <MyApp />  </StyleProvider>);

切换后,样式将从 :where 切换为类选择器:

--  :where(.css-bAMboO).ant-btn {
​
++  .css-bAMboO.ant-btn {
​
      color: #fff;
​
    }

注意:关闭 :where 降权后,你可能需要手动调整一些样式的优先级。亦或者使用 PostCSS 插件提升应用样式的优先级,PostCSS 提供了非常多的插件来调整优先级,你可以自行按需选择,例如:

通过插件配置,将你的 css 样式进行提升:

--  .my-btn {
​
++  #root .my-btn {
​
      background: red;
​
    }

CSS 逻辑属性

为了统一 LTR 和 RTL 样式,Ant Design 使用了 CSS 逻辑属性。例如原 margin-left 使用 margin-inline-start 代替,使其在 LTR 和 RTL 下都为起始位置间距。如果你需要兼容旧版浏览器(如 360 浏览器、QQ 浏览器 等等),可以通过 @ant-design/cssinjsStyleProvider 配置 transformers 将其转换:

import { legacyLogicalPropertiesTransformer, StyleProvider } from '@ant-design/cssinjs';
// `transformers` 提供预处理功能将样式进行转换export default () => (  <StyleProvider transformers={[legacyLogicalPropertiesTransformer]}>    <MyApp />  </StyleProvider>);

切换后,样式将降级 CSS 逻辑属性:

.ant-modal-root {
​
-- inset: 0;
​
++ top: 0;
​
++ right: 0;
​
++ bottom: 0;
​
++ left: 0;
​
}

10. 方案

最后采用折中方案

antd5 版本使用antd4的css,可能会出现未知问题,终极解决方法是如果想适配低级浏览器,需要antd全线降级为4

image-20240122152238298

11.查看浏览器内核

navigator.userAgent
navigator.appVersion 
navigator.appCodeName