웹팩을 사용하여 리소스 방법 및 기술을 최적화하는 방법
프런트 엔드 애플리케이션 최적화에서는 로드된 리소스의 크기를 제어하는 것이 매우 중요합니다. 대부분의 경우 우리가 할 수 있는 일은 패키징 및 컴파일 프로세스 중에 크기를 제어하고 리소스를 분할하고 재사용하는 것입니다. 이번 글에서는 webpack을 활용하여 리소스를 최적화하는 방법을 주로 소개하고 있는데, 에디터가 꽤 괜찮다고 생각해서 지금부터 공유하고 참고용으로 올려보겠습니다. 편집자를 따라 살펴보겠습니다. 모두에게 도움이 되기를 바랍니다.
머리말
이 글은 주로 웹팩 패키징을 기반으로 하며, 웹팩 패키징 수준에서 리소스와 캐시를 처리하는 방법을 설명하기 위해 React, vue 및 기타 생태학적 환경에서 개발된 단일 페이지 애플리케이션을 사용합니다. 해야 할 일은 소량의 비즈니스 코드 변경을 포함하면서 웹팩 구성 최적화를 수행하는 것입니다.
동시에 (webpack-contrib/webpack-bundle-analyzer) 플러그인을 사용하여 패키지된 리소스를 분석할 수 있습니다. 물론 이 기사에서는 이 플러그인을 선택적으로 사용할 수 있습니다. 주로 예시로 사용됩니다.
팁: 웹팩 버전 @3.6.0
1. 패키징 환경 및 코드 압축
먼저 기본 웹팩 구성이 있습니다:
// webpack.config.js const path = require('path'); const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; const PROJECT_ROOT = path.resolve(__dirname, './'); module.exports = { entry: { index: './src/index.js' }, output: { path: path.resolve(__dirname, 'dist'), filename: '[name].[chunkhash:4].js' }, module: { rules: [ { test: /\.js[x]?$/, use: 'babel-loader', include: PROJECT_ROOT, exclude: /node_modules/ } ] }, plugins: [ new BundleAnalyzerPlugin() ], resolve: { extensions: ['.js', '.jsx'] }, };
패키징을 실행하면 프로젝트의 js가 100만 개가 넘는 것을 확인할 수 있습니다.
Hash: e51afc2635f08322670b Version: webpack 3.6.0 Time: 2769ms Asset Size Chunks Chunk Names index.caa7.js 1.3 MB 0 [emitted] [big] index
이때 플러그인 `DefinePlugin` 및 `UglifyJSPlugin`만 추가하면 볼륨을 많이 줄일 수 있습니다. 플러그인에
// webpack.config.js ... { ... plugins: [ new BundleAnalyzerPlugin(), new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'production') }), new UglifyJSPlugin({ uglifyOptions: { ie8: false, output: { comments: false, beautify: false, }, mangle: { keep_fnames: true }, compress: { warnings: false, drop_console: true }, } }) ] ... }
를 추가하면 이때 패키징 출력을 볼 수 있습니다.
Hash: 84338998472a6d3c5c25 Version: webpack 3.6.0 Time: 9940ms Asset Size Chunks Chunk Names index.89c2.js 346 kB 0 [emitted] [big] index
코드 크기가 1.3M에서 346K로 줄었습니다.
(1)DefinePlugin
DefinePlugin을 사용하면 컴파일 타임에 구성할 수 있는 전역 상수를 생성할 수 있습니다. 이는 개발 모드와 릴리스 모드 빌드에 대해 서로 다른 동작을 허용하는 데 유용할 수 있습니다. 개발 빌드에서는 로깅을 수행하지만 릴리스 빌드에서는 수행하지 않는 경우 전역 상수를 사용하여 로그 여부를 결정할 수 있습니다. 이것이 DefinePlugin이 들어오는 곳이며, 이를 설정하고 개발 및 릴리스 빌드에 대한 규칙은 잊어버리세요.
비즈니스 코드 및 타사 패키지 코드에서는 다른 처리를 수행하기 위해 `process.env.NODE_ENV`를 판단해야 하는 경우가 많지만 프로덕션 환경에서는 분명히 `프로덕션`이 아닌 처리 부분이 필요하지 않습니다.
여기에서는 `process.env.NODE_ENV`를 `JSON.stringify('production')`으로 설정했는데, 이는 패키징 환경이 프로덕션 환경으로 설정되었음을 의미합니다. 그런 다음 'UglifyJSPlugin' 플러그인을 사용하면 프로덕션 환경용으로 패키징할 때 일부 중복 코드를 제거할 수 있습니다.
(2) UglifyJSPlugin
UglifyJSPlugin은 js 코드를 구문 분석하고 압축하는 데 주로 사용됩니다. js 코드를 처리하기 위해 `uglify-es`를 기반으로 합니다. https://github.com/webpack. - contrib/uglifyjs-webpack-plugin.
코드를 압축하고 중복성을 제거함으로써 패키지된 리소스의 크기가 크게 줄어듭니다.
2. 코드 분할/주문형 로딩
React 또는 Vue로 구축된 단일 페이지 애플리케이션에서 페이지 라우팅 및 뷰 제어는 프런트 엔드에서 구현되며 해당 비즈니스 로직은 js 코드에 있습니다.
애플리케이션 디자인에 페이지와 로직이 많으면 최종 생성되는 js 파일 리소스도 상당히 커집니다.
그러나 URL에 해당하는 페이지를 열 때 실제로는 모든 js 코드가 필요하지 않습니다. 우리에게 필요한 것은 다음 뷰를 로드할 때 메인 런타임 코드와 해당 비즈니스 로직 코드뿐입니다. 해당 코드 부분을 로드합니다.
따라서 이와 관련하여 수행할 수 있는 최적화는 요청 시 js 코드를 로드하는 것입니다.
지연 로딩 또는 주문형 로딩은 웹 페이지나 애플리케이션을 최적화하는 좋은 방법입니다. 이 방법은 실제로 일부 논리적 중단점에서 코드를 분리한 다음 일부 코드 블록에서 특정 작업을 완료한 후 즉시 다른 새 코드 블록을 참조하거나 참조하려고 합니다. 이렇게 하면 특정 코드 블록이 로드되지 않을 수 있으므로 앱의 초기 로드 속도가 빨라지고 전체 크기가 줄어듭니다.
Webpack은 코드 분할을 달성하기 위해 동적 가져오기 기술을 제공합니다. 먼저 webpack 구성에서 각 분할 하위 모듈의 구성을 구성해야 합니다.
// webpack.config.js const path = require('path'); const webpack = require('webpack'); const UglifyJSPlugin = require('uglifyjs-webpack-plugin'); const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; const PROJECT_ROOT = path.resolve(__dirname, './'); module.exports = { entry: { index: './src/index.js' }, output: { path: path.resolve(__dirname, 'dist'), filename: '[name].[chunkhash:4].js', chunkFilename: '[name].[chunkhash:4].child.js', }, module: { rules: [ { test: /\.js[x]?$/, use: 'babel-loader', include: PROJECT_ROOT, exclude: /node_modules/ } ] }, plugins: [ new BundleAnalyzerPlugin(), new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'production') }), new UglifyJSPlugin({ uglifyOptions: { ie8: false, output: { comments: false, beautify: false, }, mangle: { keep_fnames: true }, compress: { warnings: false, drop_console: true }, } }), ], resolve: { extensions: ['.js', '.jsx'] }, };
정의해야 할 주요 사항은 '출력'입니다. ChunkFilename`은 내보낸 분할 코드의 파일 이름입니다. 여기서는 `[name].[chunkhash:4].child.js`로 설정되어 있습니다. 여기서 `name`은 모듈 이름 또는 ID, `chunkhash에 해당합니다. `는 모듈 콘텐츠의 해시입니다.
나중에 webpack은 비즈니스 코드에서 동적으로 가져오는 두 가지 방법을 제공합니다:
`import('path/to/module') -> Promise`,
`require.ensure(종속성: 문자열 [] , callback: function(require), errorCallback: function(error), ChunkName: String)`
최신 버전의 webpack에서는 주로 `import()` 사용을 권장합니다(참고: import는 Promise를 사용하므로 코드에서 Promise 폴리필이 지원되는지 확인해야 합니다.
// src/index.js function getComponent() { return import( /* webpackChunkName: "lodash" */ 'lodash' ).then(_ => { var element = document.createElement('p'); element.innerHTML = _.join(['Hello', 'webpack'], ' '); return element; }).catch(error => 'An error occurred while loading the component'); } getComponent().then(component => { document.body.appendChild(component); })
패키징 정보를 볼 수 있습니다:
Hash: d6ba79fe5995bcf9fa4d Version: webpack 3.6.0 Time: 7022ms Asset Size Chunks Chunk Names lodash.89f0.child.js 85.4 kB 0 [emitted] lodash index.316e.js 1.96 kB 1 [emitted] index [0] ./src/index.js 441 bytes {1} [built] [2] (webpack)/buildin/global.js 509 bytes {0} [built] [3] (webpack)/buildin/module.js 517 bytes {0} [built] + 1 hidden module
패키징된 코드가 `index.316e.js`와 `lodash.89f0.child.js`라는 두 개의 파일을 생성하는 것을 볼 수 있으며, 후자는 `import`를 통해 전달됩니다. 분할을 달성합니다.
`import` 它接收一个 `path` 参数,指的是该子模块对于的路径,同时还注意到其中可以添加一行注释 `/* webpackChunkName: "lodash" */`,该注释并非是无用的,它定义了该子模块的 name,其对应与 `output.chunkFilename` 中的 `[name]`。
`import` 函数返回一个 Promise,当异步加载到子模块代码是会执行后续操作,比如更新视图等。
(1)React 中的按需加载
在 React 配合 React-Router 开发中,往往就需要代码根据路由按需加载的能力,下面是一个基于 webpack 代码动态导入技术实现的 React 动态载入的组件:
import React, { Component } from 'react'; export default function lazyLoader (importComponent) { class AsyncComponent extends Component { state = { Component: null } async componentDidMount () { const { default: Component } = await importComponent(); this.setState({ Component: Component }); } render () { const Component = this.state.Component; return Component ? <Component {...this.props} /> : null; } } return AsyncComponent; };
在 `Route` 中:
<Switch> <Route exact path="/" component={lazyLoader(() => import('./Home'))} /> <Route path="/about" component={lazyLoader(() => import('./About'))} /> <Route component={lazyLoader(() => import('./NotFound'))} /> </Switch>
在 `Route` 中渲染的是 `lazyLoader` 函数返回的组件,该组件在 mount 之后会去执行 `importComponent` 函数(既:`() => import('./About')`)动态加载其对于的组件模块(被拆分出来的代码),待加载成功之后渲染该组件。
使用该方式打包出来的代码:
Hash: 02a053d135a5653de985 Version: webpack 3.6.0 Time: 9399ms Asset Size Chunks Chunk Names 0.db22.child.js 5.82 kB 0 [emitted] 1.fcf5.child.js 4.4 kB 1 [emitted] 2.442d.child.js 3 kB 2 [emitted] index.1bbc.js 339 kB 3 [emitted] [big] index
三、抽离 Common 资源
(1)第三方库的长缓存
首先对于一些比较大的第三方库,比如在 React 中用到的 react、react-dom、react-router 等等,我们不希望它们被重复打包,并且在每次版本更新的时候也不希望去改变这部分的资源导致在用户端重新加载。
在这里可以使用 webpack 的 CommonsChunkPlugin 来抽离这些公共资源;
CommonsChunkPlugin 插件,是一个可选的用于建立一个独立文件(又称作 chunk)的功能,这个文件包括多个入口 chunk 的公共模块。通过将公共模块拆出来,最终合成的文件能够在最开始的时候加载一次,便存起来到缓存中供后续使用。这个带来速度上的提升,因为浏览器会迅速将公共的代码从缓存中取出来,而不是每次访问一个新页面时,再去加载一个更大的文件。
首先需要在 entry 中新增一个入口用来打包需要抽离出来的库,这里将 `'react', 'react-dom', 'react-router-dom', 'immutable'` 都给单独打包进 `vendor` 中;
之后在 plugins 中定义一个 `CommonsChunkPlugin` 插件,同时将其 `name` 设置为 `vendor` 是它们相关联,再将 `minChunks` 设置为 `Infinity` 防止其他代码被打包进来。
// webpack.config.js const path = require('path'); const webpack = require('webpack'); const UglifyJSPlugin = require('uglifyjs-webpack-plugin'); const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; const PROJECT_ROOT = path.resolve(__dirname, './'); module.exports = { entry: { index: './src0/index.js', vendor: ['react', 'react-dom', 'react-router-dom', 'immutable'] }, output: { path: path.resolve(__dirname, 'dist'), filename: '[name].[chunkhash:4].js', chunkFilename: '[name].[chunkhash:4].child.js', }, module: { rules: [ { test: /\.js[x]?$/, use: 'babel-loader', include: PROJECT_ROOT, exclude: /node_modules/ } ] }, plugins: [ new BundleAnalyzerPlugin(), new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'production') }), new UglifyJSPlugin({ uglifyOptions: { ie8: false, output: { comments: false, beautify: false, }, mangle: { keep_fnames: true }, compress: { warnings: false, drop_console: true }, } }), new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', minChunks: Infinity, }), ], resolve: { extensions: ['.js', '.jsx'] }, };
运行打包可以看到:
Hash: 34a71fcfd9a24e810c21 Version: webpack 3.6.0 Time: 9618ms Asset Size Chunks Chunk Names 0.2c65.child.js 5.82 kB 0 [emitted] 1.6e26.child.js 4.4 kB 1 [emitted] 2.e4bc.child.js 3 kB 2 [emitted] index.4e2f.js 64.2 kB 3 [emitted] index vendor.5fd1.js 276 kB 4 [emitted] [big] vendor
可以看到 `vendor` 被单独打包出来了。
当我们改变业务代码时再次打包:
Hash: cd3f1bc16b28ac97e20a Version: webpack 3.6.0 Time: 9750ms Asset Size Chunks Chunk Names 0.2c65.child.js 5.82 kB 0 [emitted] 1.6e26.child.js 4.4 kB 1 [emitted] 2.e4bc.child.js 3 kB 2 [emitted] index.4d45.js 64.2 kB 3 [emitted] index vendor.bc85.js 276 kB 4 [emitted] [big] vendor
vendor 包同样被打包出来的,然而它的文件 hash 却发生了变化,这显然不符合我们长缓存的需求。
这是因为 webpack 在使用 CommoChunkPlugin 的时候会生成一段 runtime 代码(它主要用来处理代码模块的映射关系),而哪怕没有改变 vendor 里的代码,这个 runtime 仍然是会跟随着打包变化的并且打入 verdor 中,所以 hash 就会开始变化了。解决方案则是把这部分的 runtime 代码也单独抽离出来,修改之前的 `CommonsChunkPlugin` 为:
// webpack.config.js ... new webpack.optimize.CommonsChunkPlugin({ name: ['vendor', 'runtime'], minChunks: Infinity, }), ...
执行打包可以看到生成的代码中多了 `runtime` 文件,同时即使改变业务代码,vendor 的 hash 值也保持不变了。
当然这段 `runtime` 实际上非常短,我们可以直接 inline 在 html 中,如果使用的是 `html-webpack-plugin` 插件处理 html,则可以结合 [`html-webpack-inline-source-plugin`](DustinJackson/html-webpack-inline-source-plugin) 插件自动处理其 inline。
(2)公共资源抽离
在我们打包出来的 js 资源包括不同入口以及子模块的 js 资源包,然而它们之间也会重复载入相同的依赖模块或者代码,因此可以通过 CommonsChunkPlugin 插件将它们共同依赖的一些资源打包成一个公共的 js 资源。
// webpack.config.js plugins: [ new BundleAnalyzerPlugin(), new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'production') }), new UglifyJSPlugin({ uglifyOptions: { ie8: false, output: { comments: false, beautify: false, }, mangle: { keep_fnames: true }, compress: { warnings: false, drop_console: true }, } }), new webpack.optimize.CommonsChunkPlugin({ name: ['vendor', 'runtime'], minChunks: Infinity, }), new webpack.optimize.CommonsChunkPlugin({ // ( 公共chunk(commnons chunk) 的名称) name: "commons", // ( 公共chunk 的文件名) filename: "commons.[chunkhash:4].js", // (模块必须被 3个 入口chunk 共享) minChunks: 3 }) ],
可以看到这里增加了 `commons` 的一个打包,当一个资源被三个以及以上 chunk 依赖时,这些资源会被单独抽离打包到 `commons.[chunkhash:4].js` 文件。
执行打包,看到结果如下:
Hash: 2577e42dc5d8b94114c8 Version: webpack 3.6.0 Time: 24009ms Asset Size Chunks Chunk Names 0.2eee.child.js 90.8 kB 0 [emitted] 1.cfbc.child.js 89.4 kB 1 [emitted] 2.557a.child.js 88 kB 2 [emitted] vendor.66fd.js 275 kB 3 [emitted] [big] vendor index.688b.js 64.2 kB 4 [emitted] index commons.a61e.js 1.78 kB 5 [emitted] commons
却发现这里的 `commons.[chunkhash].js` 基本没有实际内容,然而明明在每个子模块中也都依赖了一些相同的依赖。
借助 webpack-bundle-analyzer 来分析一波:
可以看到三个模块都依赖了 `lodash`,然而它并没有被抽离出来。
这是因为 CommonsChunkPlugin 中的 chunk 指的是 entry 中的每个入口,因此对于一个入口拆分出来的子模块(children chunk)是不生效的。
可以通过在 CommonsChunkPlugin 插件中配置 `children` 参数将拆分出来的子模块的公共依赖也打包进 `commons` 中:
// webpack.config.js plugins: [ new BundleAnalyzerPlugin(), new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'production') }), new UglifyJSPlugin({ uglifyOptions: { ie8: false, output: { comments: false, beautify: false, }, mangle: { keep_fnames: true }, compress: { warnings: false, drop_console: true }, } }), new webpack.optimize.CommonsChunkPlugin({ name: ['vendor', 'runtime'], minChunks: Infinity, }), new webpack.optimize.CommonsChunkPlugin({ // ( 公共chunk(commnons chunk) 的名称) name: "commons", // ( 公共chunk 的文件名) filename: "commons.[chunkhash:4].js", // (模块必须被 3个 入口chunk 共享) minChunks: 3 }), new webpack.optimize.CommonsChunkPlugin({ // (选择所有被选 chunks 的子 chunks) children: true, // (在提取之前需要至少三个子 chunk 共享这个模块) minChunks: 3, }) ],
查看打包效果:
其子模块的公共资源都被打包到 `index` 之中了,并没有理想地打包进 `commons` 之中,还是因为 `commons` 对于的是 entry 中的入口模块,而这里并未有 3 个 entry 模块共用资源;
在单入口的应用中可以选择去除 `commons`,而在子模块的 `CommonsChunkPlugin` 的配置中配置 `async` 为 `true`:
// webpack.config.js plugins: [ new BundleAnalyzerPlugin(), new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'production') }), new UglifyJSPlugin({ uglifyOptions: { ie8: false, output: { comments: false, beautify: false, }, mangle: { keep_fnames: true }, compress: { warnings: false, drop_console: true }, } }), new webpack.optimize.CommonsChunkPlugin({ name: ['vendor', 'runtime'], minChunks: Infinity, }), new webpack.optimize.CommonsChunkPlugin({ // (选择所有被选 chunks 的子 chunks) children: true, // (异步加载) async: true, // (在提取之前需要至少三个子 chunk 共享这个模块) minChunks: 3, }) ],
查看效果:
子模块的公共资源都被打包到 `0.9c90.child.js` 中了,该模块则是子模块的 commons。
四、tree shaking
tree shaking 是一个术语,通常用于描述移除 JavaScript 上下文中的未引用代码(dead-code)。它依赖于 ES2015 模块系统中的静态结构特性,例如 import 和 export。这个术语和概念实际上是兴起于 ES2015 模块打包工具 rollup。
在我们引入一个依赖的某个输出的时候,我们可能需要的仅仅是该依赖的某一部分代码,而另一部分代码则是 `unused` 的,如果能够去除这部分代码,那么最终打包出来的资源体积也是可以有可观的减小。
首先,webpack 中实现 tree shaking 是基于 webpack 内部支持的 es2015 的模块机制,在大部分时候我们使用 babel 来编译 js 代码,而 babel 会通过自己的模块加载机制处理一遍,这导致 webpack 中的 tree shaking 处理将会失效。因此在 babel 的配置中需要关闭对模块加载的处理:
// .babelrc { "presets": [ [ "env", { "modules": false, } ], "stage-0" ], ... }
然后我们来看下 webpack 是如何处理打包的代码,举例有一个入口文件 `index.js` 和一个 `utils.js` 文件:
// utils.js export function square(x) { return x * x; } export function cube(x) { return x * x * x; } " "js // index.js import { cube } from './utils.js'; console.log(cube(10)); " 打包出来的代码: " // index.bundle.js /* 1 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; /* unused harmony export square */ /* harmony export (immutable) */ __webpack_exports__["a"] = cube; function square(x) { return x * x; } function cube(x) { return x * x * x; }
可以看到仅有 `cube` 函数被 `__webpack_exports__` 导出来,而 `square` 函数被标记为 `unused harmony export square`,然而在打包代码中既是 `square` 没有被导出但是它仍然存在与代码中,而如何去除其代码则可以通过添加 `UglifyjsWebpackPlugin` 插件来处理。
相关推荐:
위 내용은 웹팩을 사용하여 리소스 방법 및 기술을 최적화하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











Vue는 대화형의 효율적인 웹 애플리케이션을 신속하게 구축하는 데 도움이 되는 탁월한 JavaScript 프레임워크입니다. Vue3은 Vue의 최신 버전으로, 많은 새로운 특징과 기능을 도입했습니다. Webpack은 현재 프로젝트의 다양한 리소스를 관리하는 데 도움이 되는 가장 인기 있는 JavaScript 모듈 패키저 및 빌드 도구 중 하나입니다. 이 기사에서는 Webpack을 사용하여 Vue3 애플리케이션을 패키징하고 빌드하는 방법을 소개합니다. 1. 웹팩 설치

115 네트워크 디스크에는 많은 리소스가 있을 것인데 리소스를 찾는 방법은 무엇입니까? 사용자는 소프트웨어에서 필요한 리소스를 검색한 다음 다운로드 인터페이스로 들어간 다음 네트워크 디스크에 저장하도록 선택할 수 있습니다. 115 네트워크 디스크에서 리소스를 찾는 방법에 대한 이 소개는 구체적인 내용을 알려줄 수 있습니다. 다음은 자세한 소개입니다. 와서 살펴보세요. 115 네트워크 디스크에서 리소스를 찾는 방법 답변: 소프트웨어에서 콘텐츠를 검색한 다음 클릭하여 네트워크 디스크에 저장합니다. 자세한 소개: 1. 먼저 앱에서 원하는 리소스를 입력하세요. 2. 그러면 나타나는 키워드 링크를 클릭하세요. 3. 그런 다음 다운로드 인터페이스로 들어갑니다. 4. 내부 네트워크 디스크에 저장을 클릭합니다.

한샤오취안은 한국 드라마를 많이 볼 수 있는 소프트웨어인데 왜 갑자기 리소스가 없나요? 이 소프트웨어는 네트워크 문제, 버전 문제 또는 저작권 문제로 인해 리소스가 없을 수 있습니다. Han Xiaoquan이 갑자기 자원이 없는 이유에 대한 이 기사는 구체적인 내용을 알려줄 수 있습니다. 다음은 자세한 소개입니다. 와서 살펴보세요. Han Xiaoquan에 갑자기 리소스가 없는 이유는 무엇입니까? 답변: 네트워크 문제, 버전 문제 및 저작권 문제로 인해 자세한 소개: 1. 네트워크 문제 해결 방법: 다른 네트워크를 선택한 다음 소프트웨어에 다시 로그인하여 시도해 볼 수 있습니다. . 2. 버전 문제 해결: 사용자는 공식 웹사이트에서 이 소프트웨어의 최신 버전을 다운로드할 수 있습니다. 3. 저작권 문제 해결: 저작권 문제로 인해 일부 한국 드라마가 목록에서 제거되었습니다. 다른 한국 드라마를 선택하여 시청할 수 있습니다.

JavaAPI 개발에서 웹 서버 처리를 위해 Jetty7 사용 인터넷의 발전과 함께 웹 서버는 애플리케이션 개발의 핵심 부분이 되었으며 많은 기업의 초점이기도 합니다. 증가하는 비즈니스 요구를 충족하기 위해 많은 개발자가 웹 서버 개발에 Jetty를 사용하기로 선택했으며 그 유연성과 확장성은 널리 인정받고 있습니다. 이 기사에서는 We 용 JavaAPI 개발에서 Jetty7을 사용하는 방법을 소개합니다.

얼굴 차단 사격은 영상 속 인물을 가리지 않고 다수의 사격이 떠다니는 것처럼 보이도록 하여 마치 인물 뒤에서 떠다니는 것처럼 보이게 하는 것을 의미합니다. 기계 학습은 몇 년 동안 널리 사용되었지만 많은 사람들은 이러한 기능을 브라우저에서도 실행할 수 있다는 사실을 모릅니다. 이 기사에서는 기사 마지막 부분에 적용 가능한 몇 가지 시나리오를 소개합니다. 이 솔루션을 통해 몇 가지 아이디어를 얻을 수 있기를 바랍니다. mediapipeDemo(https://google.github.io/mediapipe/)는 주류 얼굴 차단 공세 주문형 업로드의 구현 원리를 보여줍니다. 비디오 서버 백그라운드 계산은 비디오 화면의 세로 영역을 추출하고 이를 svg로 변환합니다. 클라이언트가 비디오를 재생하는 동안 서버에서 svg를 다운로드하고 사격, 초상화와 결합합니다.

양식 유효성 검사는 웹 애플리케이션 개발에서 매우 중요한 링크로, 애플리케이션의 보안 취약성과 데이터 오류를 방지하기 위해 양식 데이터를 제출하기 전에 데이터의 유효성을 확인할 수 있습니다. Golang을 사용하여 웹 애플리케이션에 대한 양식 유효성 검사를 쉽게 구현할 수 있습니다. 이 기사에서는 Golang을 사용하여 웹 애플리케이션에 대한 양식 유효성 검사를 구현하는 방법을 소개합니다. 1. 폼 유효성 검사의 기본 요소 폼 유효성 검사를 구현하는 방법을 소개하기 전에 먼저 폼 유효성 검사의 기본 요소가 무엇인지 알아야 합니다. 양식 요소: 양식 요소는

Cockpit은 Linux 서버용 웹 기반 그래픽 인터페이스입니다. 이는 주로 신규/전문가 사용자가 Linux 서버를 보다 쉽게 관리할 수 있도록 하기 위한 것입니다. 이 문서에서는 Cockpit 액세스 모드와 CockpitWebUI에서 Cockpit으로 관리 액세스를 전환하는 방법에 대해 설명합니다. 콘텐츠 항목: Cockpit 입장 모드 현재 Cockpit 액세스 모드 찾기 CockpitWebUI에서 Cockpit에 대한 관리 액세스 활성화 CockpitWebUI에서 Cockpit에 대한 관리 액세스 비활성화 결론 조종석 입장 모드 조종석에는 두 가지 액세스 모드가 있습니다. 제한된 액세스: 이는 조종석 액세스 모드의 기본값입니다. 이 액세스 모드에서는 조종석에서 웹 사용자에 액세스할 수 없습니다.

웹 표준은 W3C 및 기타 관련 기관에서 개발한 일련의 사양 및 지침으로, HTML, CSS, JavaScript, DOM, 웹 접근성 및 성능 최적화를 포함하며, 이러한 표준을 따르면 페이지의 호환성이 향상됩니다. 접근성, 유지 관리성 및 성능. 웹 표준의 목표는 웹 콘텐츠가 다양한 플랫폼, 브라우저 및 장치에서 일관되게 표시되고 상호 작용할 수 있도록 하여 더 나은 사용자 경험과 개발 효율성을 제공하는 것입니다.
