时下最流行前端构建工具Webpack 入门总结

发表于 3年以前  | 总阅读数:374 次

最近梳理了下以前 webpack 的相关开发经验,整理和总结了一份入门笔记,欢迎大家围观和批评指正。

随着 web 应用越来越复杂和庞大,前端技术迅猛发展,各路大神各显神通,多种优秀的前端框架、新语言和其他相关技术(如下图所示)不断涌现,这些都极大地提高了我们的开发效率。

前端技术栈

然鹅,我们都知道这些技术都有一个共同点,那就是源代码都无法直接在浏览器上运行。此时,我们就需要通过构建工具将这些代码转换成浏览器可执行的 JS、CSS、HTML。这对前端构建工具有了更高的要求。

历史上也出现了一系列构建工具,一些常见的如下:

常见的构建工具

其中,Webpack 凭借其强大的功能与良好的使用体验,还有有庞大的社区支持,在众多构建工具中脱颖而出成为时下最流行的构建工具。

在言归正传之前,我们先来简单了解一下 webpack。

webpack

Webpack 简介

根据官网介绍,Webpack 是一个用于现代 JavaScript 应用程序的 静态模块打包工具。当 webpack 处理应用程序时,它会在内部从一个或多个入口点构建一个 依赖图(dependency graph),然后将你项目中所需的每一个模块组合成一个或多个 bundles,它们均为静态资源,用于展示你的内容。

Webpack 一些核心概念:

  • Entry:入口,指示 Webpack 应该使用哪个模块,来作为构建其内部 依赖图(dependency graph) 的开始。
  • Output:输出结果,告诉 Webpack 在哪里输出它所创建的 bundle,以及如何命名这些文件。
  • Module:模块,在 Webpack 里一切皆模块,一个模块对应着一个文件。Webpack 会从配置的 Entry 开始递归找出所有依赖的模块。
  • Chunk:代码块,一个 Chunk 由多个模块组合而成,用于代码合并与分割。
  • Loader:模块代码转换器,让 webpack 能够去处理除了 JS、JSON 之外的其他类型的文件,并将它们转换为有效 模块,以供应用程序使用,以及被添加到依赖图中。
  • Plugin:扩展插件。在 webpack 运行的生命周期中会广播出许多事件,plugin 可以监听这些事件,在合适的时机通过 webpack 提供的 api 改变输出结果。常见的有:打包优化,资源管理,注入环境变量。
  • Mode:模式,告知 webpack 使用相应模式的内置优化
  • Browser Compatibility:浏览器兼容性,Webpack 支持所有符合 ES5 标准 的浏览器(IE8 以上版本)

Webpack 的作用

Webpack 的作用非常多,简单列举几点如下:

我们可以通过 loader 和 plugin 机制去进一步扩展能力,按照项目需要去实现个性化的功能。

铺垫了那么多,现在回归主题吧!

Webpack 是由 nodejs 编写的前端资源加载/打包工具,由 nodejs 提供了强大的文件处理,IO 能力。

Loader 和 Plugin 在 Webpack 里是支柱能力。在整个构建流程中,Loader 和 Plugin 对编译结果起着决定性的作用,下面主要讲一下 Webpack 中一些常用的 Loader 和 Plugin。

Loader

简介

webpack 中提供了一种处理多种文件格式的机制,这便是 Loader,我们可以把 Loader 当成一个转换器,它可以将某种格式的文件转换成 Wwebpack 支持打包的模块。

在 Webpack 中,一切皆模块,我们常见的 Javascript、CSS、Less、Typescript、Jsx、图片等文件都是模块,不同模块的加载是通过模块加载器来统一管理的,当我们需要使用不同的 Loader 来解析不同类型的文件时,我们可以在 module.rules 字段下配置相关规则。

loader 特点
  • loader 本质上是一个函数,output=loader(input) // input 可为工程源文件的字符串,也可是上一个 loader 转化后的结果;
  • 第一个 loader 的传入参数只有一个:资源文件(resource file)的内容;
  • loader 支持链式调用,webpack 打包时是按照数组从后往前的顺序将资源交给 loader 处理的。
  • 支持同步或异步函数。
代码结构

代码结构通常如下:

// source:资源输入,对于第一个执行的 loader 为资源文件的内容;后续执行的 loader 则为前一个 loader 的执行结果
// sourceMap: 可选参数,代码的 sourcemap 结构
// data: 可选参数,其它需要在 Loader 链中传递的信息,比如 posthtml/posthtml-loader 就会通过这个参数传递参数的 AST 对象

const loaderUtils = require('loader-utils');
module.exports = function(source, sourceMap?, data?) {
  // 获取到用户给当前 Loader 传入的 options
  const options = loaderUtils.getOptions(this);
  // TODO: 此处为转换source的逻辑
  return source;
};

常用的 Loader

1. babel-loader

babel-loader 基于 babel,用于解析 JavaScript 文件。babel 有丰富的预设和插件,babel 的配置可以直接写到 options 里或者单独写道配置文件里。

Babel 是一个 Javscript 编译器,可以将高级语法(主要是 ECMAScript 2015+ )编译成浏览器支持的低版本语法,它可以帮助你用最新版本的 Javascript 写代码,提高开发效率。

webpack 通过 babel-loader 使用 Babel。

用法

# 环境要求:
webpack 4.x || 5.x | babel-loader 8.x | babel 7.x

# 安装依赖包:
npm install -D babel-loader @babel/core @babel/preset-env webpack

然后,我们需要建立一个 Babel 配置文件来指定编译的规则。

Babel 配置里的两大核心:插件数组(plugins) 和 预设数组(presets)。

Babel 的预设(preset)可以被看作是一组 Babel 插件的集合,由一系列插件组成。

常用预设:

  • @babel/preset-env ES2015+ 语法
  • @babel/preset-typescript TypeScript
  • @babel/preset-react React
  • @babel/preset-flow Flow

插件和预设的执行顺序:

  • 插件比预设先执行
  • 插件执行顺序是插件数组从前向后执行
  • 预设执行顺序是预设数组从后向前执行

webpack 配置代码:

// webpack.config.js
module: {
  rules: [
    {
      test: /\.m?js$/,
      exclude: /node_modules/,
      use: {
        loader: 'babel-loader',
        options: {
          presets: [
            ['@babel/preset-env', { targets: "defaults" }]
          ],
          plugins: ['@babel/plugin-proposal-class-properties'],
          // 缓存 loader 的执行结果到指定目录,默认为node_modules/.cache/babel-loader,之后的 webpack 构建,将会尝试读取缓存
          cacheDirectory: true,
        }
      }
    }
  ]
}

以上 options 参数也可单独写到配置文件里,许多其他工具都有类似的配置文件:ESLint (.eslintrc)、Prettier (.prettierrc)。

配置文件我们一般只需要配置 presets(预设数组) 和 plugins(插件数组) ,其他一般也用不到,代码示例如下:

// babel.config.js
module.exports = (api) => {
    return {
        presets: [
            '@babel/preset-react',
            [
                '@babel/preset-env', {
                    useBuiltIns: 'usage',
                    corejs: '2',
                    targets: {
                        chrome: '58',
                        ie: '10'
                    }
                }
            ]
        ],
        plugins: [
            '@babel/plugin-transform-react-jsx',
            '@babel/plugin-proposal-class-properties'
        ]
    };
};
2. ts-loader

为 webpack 提供的 TypeScript loader,打包编译 Typescript。

安装依赖:


npm install ts-loader --save-dev
npm install typescript --dev

webpack 配置如下:

// webpack.config.json
module.exports = {
  mode: "development",
  devtool: "inline-source-map",
  entry: "./app.ts",
  output: {
    filename: "bundle.js"
  },
  resolve: {
    // Add `.ts` and `.tsx` as a resolvable extension.
    extensions: [".ts", ".tsx", ".js"]
  },
  module: {
    rules: [
      // all files with a `.ts` or `.tsx` extension will be handled by `ts-loader`
      { test: /\.tsx?$/, loader: "ts-loader" }
    ]
  }
};

还需要 typescript 编译器的配置文件tsconfig.json

{
  "compilerOptions": {
    // 目标语言的版本
    "target": "esnext",
    // 生成代码的模板标准
    "module": "esnext",
    "moduleResolution": "node",
    // 允许编译器编译JS,JSX文件
    "allowJS": true,
    // 允许在JS文件中报错,通常与allowJS一起使用
    "checkJs": true,
    "noEmit": true,
    // 是否生成source map文件
    "sourceMap": true,
    // 指定jsx模式
    "jsx": "react"
  },
  // 编译需要编译的文件或目录
  "include": [
    "src",
    "test"
  ],
  // 编译器需要排除的文件或文件夹
  "exclude": [
    "node_modules",
    "**/*.spec.ts"
  ]
}
3. markdown-loader

markdown 编译器和解析器

用法:只需将 loader 添加到您的配置中,并设置 options。

js 代码里引入 markdown 文件:

// file.js
import md from 'markdown-file.md';
console.log(md);

webpack 配置:

// wenpack.config.js
const marked = require('marked');
const renderer = new marked.Renderer();
module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /\.md$/,
        use: [
            {
                loader: 'html-loader'
            },
            {
                loader: 'markdown-loader',
                options: {
                    pedantic: true,
                    renderer
                }
            }
        ]
      }
    ],
  },
};
4. raw-loader

可将文件作为字符串导入:

// app.js
import txt from './file.txt';

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.txt$/,
        use: 'raw-loader'
      }
    ]
  }
}
5. file-loader

用于处理文件类型资源,如 jpg,png 等图片。返回值为 publicPath 为准:

// file.js
import img from './webpack.png';
console.log(img); // 编译后:https://www.tencent.com/webpack_605dc7bf.png

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.(png|jpe?g|gif)$/i,
        loader: 'file-loader',
        options: {
          name: '[name]_[hash:8].[ext]',
          publicPath: "https://www.tencent.com",
        },
      },
    ],
  },
};

css 文件里的图片路径变成如下:

/* index.less */
.tag {
  background-color: red;
  background-image: url(./webpack.png);
}
/* 编译后:*/
background-image: url(https://www.tencent.com/webpack_605dc7bf.png);
6. url-loader

它与 file-loader 作用相似,也是处理图片的,只不过 url-loader 可以设置一个根据图片大小进行不同的操作,如果该图片大小大于指定的大小,则将图片进行打包资源,否则将图片转换为 base64 字符串合并到 js 文件里。

module.exports = {
  module: {
    rules: [
      {
        test: /\.(png|jpg|jpeg)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              name: '[name]_[hash:8].[ext]',
              // 这里单位为(b) 10240 => 10kb
              // 这里如果小于10kb则转换为base64打包进js文件,如果大于10kb则打包到对应目录
              limit: 10240,
            }
          }
        ]
      }
    ]
  }
}
7. svg-sprite-loader

会把引用的 svg 文件 塞到一个个 symbol 中,合并成一个大的 SVG sprite,使用时则通过 SVG 的 传入图标 id 后渲染出图标。最后将这个大的 svg 放入 body 中。symbol 的 id 如果不特别指定,就是你的文件名。

该 loader 可以搭配svgo-loader一起使用,svgo-loader 是 svg 的优化器,它可以删除和修改 SVG 元素,折叠内容,移动属性等,具体不展开描述。感兴趣的可以移步[官方介绍]

用途:可以用来开发统一的图标管理库。

效果

示例代码:

// js文件里用法
import webpack from './webpack/webpack.svg';
const type = 'webpack';
const svg =  `<svg>
    <use xlink:href="#${type}"/>
  </svg>`;
const dom = `<div class="tag">
  ${svg}
  </div>`;

document.getElementById('react-app').innerHTML = dom;

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.(png|jpg|jpeg)$/,
        use: [
          {
            test: /\.svg$/,
            use: [
                {
                  loader: 'svg-sprite-loader'
                },
                'svgo-loader'
            ]
          },
        ]
      }
    ]
  }
}

原理:利用 svg 的 symbol 元素,将每个 icon 包裹在 symbol 中,通过 use 使用该 symbol。

8. style-loader

通过注入标签的方式引入 CSS 的,加载会更快;

  • 不要将 style-loader 和 mini-css-extract-plugin 针对同一个 CSS 模块一起使用!
  • 代码示例见下文 postcss-loader。

    9. css-loader

    仅处理 css 的各种加载语法(@import 和 url()函数等),就像 js 解析 import/require() 一样。

    代码示例见下文 postcss-loader。

    10. postcss-loader

    PostCSS 是一个允许使用 JS 插件转换样式的工具。这些插件可以检查(lint)你的 CSS,支持 CSS Variables 和 Mixins, 编译尚未被浏览器广泛支持的先进的 CSS 语法,内联图片,以及其它很多优秀的功能。

    PostCSS 在业界被广泛地应用。PostCSS 的autoprefixer插件是最流行的 CSS 处理工具之一。autoprefixer 添加了浏览器前缀,它使用 Can I Use 上面的数据。

    安装

    npm install postcss-loader autoprefixer --save-dev
    

    代码示例:

    // webpack.config.js
    const MiniCssExtractPlugin = require('mini-css-extract-plugin');
    const isDev = process.NODE_ENV === 'development';
    
    module.exports = {
      module: {
        rules: [
          {
            test: /\.(css|less)$/,
            exclude: /node_modules/,
            use: [
              isDev ? 'style-loader' : MiniCssExtractPlugin.loader,
              {
                loader: 'css-loader',
                options: {
                  importLoaders: 1,
                }
              },
              {
                loader: 'postcss-loader'
              },
              {
                  loader: 'less-loader',
                  options: {
                      lessOptions: {
                          javascriptEnabled: true
                      }
                  }
              }
            ]
          }
        ]
      }
    }

    然后在项目根目录创建 postcss.config.js,并且设置支持哪些浏览器,必须设置支持的浏览器才会自动添加添加浏览器兼容:

    module.exports = {
      plugins: [
        require('precss'),
        require('autoprefixer')({
          'browsers': [
            'defaults',
            'not ie < 11',
            'last 2 versions',
            '> 1%',
            'iOS 7',
            'last 3 iOS versions'
          ]
        })
      ]
    }

    截止到目前,PostCSS 有 200 多个插件。你可以在[插件列表] 或[搜索目录] 找到它们。

    11. less-loader

    解析 less,转换为 css。

    代码示例见上文 postcss-loader

    Plugin

    Plugin 简介

    Webpack 就像一条生产线,要经过一系列处理流程后才能将源文件转换成输出结果。这条生产线上的每个处理流程的职责都是单一的,多个流程之间有存在依赖关系,只有完成当前处理后才能交给下一个流程去处理。插件就像是一个插入到生产线中的一个功能,在特定的时机对生产线上的资源做处理。

    Webpack 通过 Tapable 来组织这条复杂的生产线。Webpack 在运行过程中会广播事件,插件只需要监听它所关心的事件,就能加入到这条生产线中,去改变生产线的运作。Webpack 的事件流机制保证了插件的有序性,使得整个系统扩展性很好。

    ——「深入浅出 Webpack」

    常用 Plugin

    1. copy-webpack-plugin

    将已经存在的单个文件或整个目录复制到构建目录。

    const CopyPlugin = require("copy-webpack-plugin");
    module.exports = {
      plugins: [
        new CopyPlugin({
          patterns: [
            {
              from: './template/page.html',
              to: `${__dirname}/output/cp/page.html`
            },
          ],
        }),
      ],
    };
    2. html-webpack-plugin

    基本作用是生成 html 文件:

    • 单页应用可以生成一个 html 入口,多页应用可以配置多个 html-webpack-plugin 实例来生成多个页面入口;
    • 为 html 引入外部资源如 script、link,将 entry 配置的相关入口 chunk 以及 mini-css-extract-plugin 抽取的 css 文件插入到基于该插件设置的 template 文件生成的 html 文件里面,具体的方式是 link 插入到 head 中,script 插入到 head 或 body 中。
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    module.exports = {
      entry: {
        news: [path.resolve(__dirname, '../src/news/index.js')],
        video: path.resolve(__dirname, '../src/video/index.js'),
      },
      plugins: [
        new HtmlWebpackPlugin({
          title: 'news page',
          // 生成的文件名称 相对于webpackConfig.output.path路径而言
          filename: 'pages/news.html',
          // 生成filename的文件模板
          template: path.resolve(__dirname, '../template/news/index.html'),
          chunks: ['news']
        }),
        new HtmlWebpackPlugin({
          title: 'video page',
          // 生成的文件名称
          filename: 'pages/video.html',
          // 生成filename的文件模板
          template: path.resolve(__dirname, '../template/video/index.html'),
          chunks: ['video']
        }),
      ]
    };
    3. clean-webpack-plugin

    默认情况下,这个插件会删除 webpack 的 output.path 中的所有文件,以及每次成功重新构建后所有未使用的资源。

    这个插件在生产环境用的频率非常高,因为生产环境经常会通过 hash 生成很多 bundle 文件,如果不进行清理的话每次都会生成新的,导致文件夹非常庞大。

    const HtmlWebpackPlugin = require('html-webpack-plugin');
    module.exports = {
      entry: {
        news: [path.resolve(__dirname, '../src/news/index.js')],
        video: path.resolve(__dirname, '../src/video/index.js'),
      },
      plugins: [
        new HtmlWebpackPlugin({
          title: 'news page',
          // 生成的文件名称 相对于webpackConfig.output.path路径而言
          filename: 'pages/news.html',
          // 生成filename的文件模板
          template: path.resolve(__dirname, '../template/news/index.html'),
          chunks: ['news']
        }),
        new HtmlWebpackPlugin({
          title: 'video page',
          // 生成的文件名称
          filename: 'pages/video.html',
          // 生成filename的文件模板
          template: path.resolve(__dirname, '../template/video/index.html'),
          chunks: ['video']
        }),
      ]
    };
    4. mini-css-extract-plugin

    本插件会将 CSS 提取到单独的文件中,为每个包含 CSS 的 JS 文件创建一个 CSS 文件。

    const { CleanWebpackPlugin } = require('clean-webpack-plugin');
    module.exports = {
        plugins: [
            new CleanWebpackPlugin(),
        ]
    };

    可以结合上文关于 style-loader 的介绍一起了解该插件。

    5. webpack.HotModuleReplacementPlugin

    模块热替换插件,除此之外还被称为 HMR。

    该功能会在应用程序运行过程中,替换、添加或删除 模块,而无需重新加载整个页面。主要是通过以下几种方式,来显著加快开发速度:

    • 保留在完全重新加载页面期间丢失的应用程序状态;
    • 只更新变更内容,以节省宝贵的开发时间;
    • 在源代码中 CSS/JS 产生修改时,会立刻在浏览器中进行更新,这几乎相当于在浏览器 devtools 直接更改样式。

    启动方式有 2 种:

    • 引入插件 webpack.HotModuleReplacementPlugin 并且设置 devServer.hot: true
    • 命令行加 --hot 参数

    package.json 配置:

    // 建议 mini-css-extract-plugin 与 css-loader 一起使用
    // 将 loader 与 plugin 添加到 webpack 配置文件中
    
    const MiniCssExtractPlugin = require('mini-css-extract-plugin');
    module.exports = {
      plugins: [new MiniCssExtractPlugin()],
      module: {
        rules: [
          {
            test: /\.css$/i,
            use: [MiniCssExtractPlugin.loader, 'css-loader'],
          },
        ],
      },
    };

    webpack 的配置如下:

    // scripts/dev.config.js文件
    const webpack = require('webpack');
    const path = require('path');
    const outputPath = path.resolve(__dirname, './output/public');
    module.exports = {
      mode: 'development',
      entry: {
        preview: [
          './node_modules/webpack-dev-server/client/index.js?path=http://localhost:9000',
          path.resolve(__dirname, '../src/preview/index.js')
        ],
      },
      output: {
        filename: 'static/js/[name]/index.js',
        // 动态生成的chunk在输出时的文件名称
        chunkFilename: 'static/js/[name]/chunk_[chunkhash].js',
        path: outputPath
      },
      plugins: [
        // 大多数情况下不需要任何配置
        new webpack.HotModuleReplacementPlugin(),
      ],
      devServer: {
            // 仅在需要提供静态文件时才进行配置
            contentBase: outputPath,
            // publicPath: '', // 值默认为'/'
            compress: true,
            port: 9000,
            watchContentBase: true,
            hot: true,
            // 在服务器启动后打开浏览器
            open: true,
            // 指定打开浏览器时要浏览的页面
            openPage: ['pages/preview.html'],
            // 将产生的文件写入硬盘。 写入位置为 output.path 配置的目录
            writeToDisk: true,
        }
    }

    注意:HMR 绝对不能被用在生产环境。

    6. webpack.DefinePlugin

    创建一个在编译时可以配置的全局常量。这会对开发模式和生产模式的构建允许不同的行为非常有用。因为这个插件直接执行文本替换,给定的值必须包含字符串本身内的实际引号。

    通常,有两种方式来达到这个效果,使用'"production"', 或者使用 JSON.stringify('production')

    // webpack.config.js
    const isProd = process.env.NODE_ENV === 'production';
    module.exports = {
      plugins: [
        new webpack.DefinePlugin({
          PAGE_URL: JSON.stringify(isProd
            ? 'https://www.tencent.com/page'
            : 'http://testsite.tencent.com/page'
            )
        }),
      ]
    }
    
    // 代码里面直接使用
    console.log(PAGE_URL);
    7. webpack-bundle-analyzer

    可以看到项目各模块的大小,可以按需优化.一个 webpack 的 bundle 文件分析工具,将 bundle 文件以可交互缩放的 treemap 的形式展示。

    const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
    module.exports = {
      plugins: [
        new BundleAnalyzerPlugin()
      ]
    }

    启动服务:

    • 生产环境查看:NODE_ENV=production npm run build
    • 开发环境查看:NODE_ENV=development npm run start

    最终效果:

    了解更多请移步链接

    8. SplitChunksPlugin

    代码分割。

    <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/Iic9WLWEQMg0xFBwAjJ2zTcXVTdTvf1Hf9Qr960V5tkDF4nBI00vFAkp1xcVzWjtiaacCnUh9v6JgBsUdxJxoX5EuQE8BsLAWt/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(248, 248, 248);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;">```
    <span style="color: #0086b3;line-height: 26px;">module.exports = {<br></br>  <span style="line-height: 26px;">optimization: {<br></br>    <span style="line-height: 26px;">splitChunks: {<br></br>      <span style="color: #998;font-style: italic;line-height: 26px;">// 分隔符<br></br>      <span style="color: #998;font-style: italic;line-height: 26px;">// automaticNameDelimiter: '~',<br></br>      <span style="color: #998;font-style: italic;line-height: 26px;">// all, async, and initial<br></br>      <span style="line-height: 26px;">chunks: <span style="color: #d14;line-height: 26px;">'all',<br></br>      <span style="color: #998;font-style: italic;line-height: 26px;">// 它可以继承/覆盖上面 splitChunks 中所有的参数值,除此之外还额外提供了三个配置,分别为:test, priority 和 reuseExistingChunk<br></br>      <span style="line-height: 26px;">cacheGroups: {<br></br>        <span style="line-height: 26px;">vendors: {<br></br>          <span style="color: #998;font-style: italic;line-height: 26px;">// 表示要过滤 modules,默认为所有的 modules,可匹配模块路径或 chunk 名字,当匹配的是 chunk 名字的时候,其里面的所有 modules 都会选中<br></br>          <span style="line-height: 26px;">test: <span style="color: #009926;line-height: 26px;">/[\\/]node_modules\/antd\//,<br></br>          <span style="color: #998;font-style: italic;line-height: 26px;">// priority:表示抽取权重,数字越大表示优先级越高。因为一个 module 可能会满足多个 cacheGroups 的条件,那么抽取到哪个就由权重最高的说了算;<br></br>          <span style="color: #998;font-style: italic;line-height: 26px;">// priority: 3,<br></br>          <span style="color: #998;font-style: italic;line-height: 26px;">// reuseExistingChunk:表示是否使用已有的 chunk,如果为 true 则表示如果当前的 chunk 包含的模块已经被抽取出去了,那么将不会重新生成新的。<br></br>          <span style="line-height: 26px;">reuseExistingChunk: <span style="color: #008080;line-height: 26px;">true,<br></br>          <span style="line-height: 26px;">name: <span style="color: #d14;line-height: 26px;">'antd'<br></br>        }<br></br>      }<br></br>    }<br></br>  },<br></br>}<br></br>
    
    
    
    腾讯程序员视频号直播来了!![](https://oss-cn-hangzhou.aliyuncs.com/codingsky/cdn/img/2021-10-15/c943a8e045050d709bcf5a54fb20e339)
    
    
    腾讯程序员视频号最新视频**一键轻松转换PDF与Office**

    本文由哈喽比特于3年以前收录,如有侵权请联系我们。
    文章来源:https://mp.weixin.qq.com/s/vdOnXCUGWv6oEEIaKOXFuQ

     相关推荐

    刘强东夫妇:“移民美国”传言被驳斥

    京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

    发布于:1年以前  |  808次阅读  |  详细内容 »

    博主曝三大运营商,将集体采购百万台华为Mate60系列

    日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

    发布于:1年以前  |  770次阅读  |  详细内容 »

    ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

    据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

    发布于:1年以前  |  756次阅读  |  详细内容 »

    抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

    今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

    发布于:1年以前  |  648次阅读  |  详细内容 »

    威马CDO:中国每百户家庭仅17户有车

    日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

    发布于:1年以前  |  589次阅读  |  详细内容 »

    研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

    近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

    发布于:1年以前  |  449次阅读  |  详细内容 »

    苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

    据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

    发布于:1年以前  |  446次阅读  |  详细内容 »

    千万级抖音网红秀才账号被封禁

    9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

    发布于:1年以前  |  445次阅读  |  详细内容 »

    亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

    9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

    发布于:1年以前  |  444次阅读  |  详细内容 »

    苹果上线AppsbyApple网站,以推广自家应用程序

    据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

    发布于:1年以前  |  442次阅读  |  详细内容 »

    特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

    特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

    发布于:1年以前  |  441次阅读  |  详细内容 »

    光刻机巨头阿斯麦:拿到许可,继续对华出口

    据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

    发布于:1年以前  |  437次阅读  |  详细内容 »

    马斯克与库克首次隔空合作:为苹果提供卫星服务

    近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

    发布于:1年以前  |  430次阅读  |  详细内容 »

    𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

    据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

    发布于:1年以前  |  428次阅读  |  详细内容 »

    荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

    9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

    发布于:1年以前  |  423次阅读  |  详细内容 »

    AI操控无人机能力超越人类冠军

    《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

    发布于:1年以前  |  423次阅读  |  详细内容 »

    AI生成的蘑菇科普书存在可致命错误

    近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

    发布于:1年以前  |  420次阅读  |  详细内容 »

    社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

    社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

    发布于:1年以前  |  411次阅读  |  详细内容 »

    国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

    2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

    发布于:1年以前  |  406次阅读  |  详细内容 »

    罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

    罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

    发布于:1年以前  |  398次阅读  |  详细内容 »
     相关文章
    Android插件化方案 5年以前  |  237287次阅读
    vscode超好用的代码书签插件Bookmarks 2年以前  |  8126次阅读
     目录