webpack基礎入門知道教程
本文github倉庫位址: ,其中包含了本教學的所有程式碼。
【如果你覺得這篇文章寫得不錯,麻煩給本倉庫一顆星:-D】
#1. 導語
1.1 什麼叫做webpack
webpack is a module bundler.
webpack takes modules with dependencies and generates static assets representing those modules.
簡單的概括就是:webpack是一個模組打包工具,處理模組之間的依賴同時產生對應模組的靜態資源。
1.2 webpack可以做些什麼事情
圖已經很清楚的反應了幾個資訊:
webpack把專案中所有的靜態檔案都看成一個模組
模快之間存在著一些列的依賴
多頁面的靜態資源產生(打包之後產生多個靜態文件,涉及到程式碼拆分)
#2.webpack安裝
-
全域安裝(供全域呼叫:如
webpack --config webpack.config.js
)npm install -g webpack
登入後複製 專案安裝
"javascript
npm install webpack
// 處理類似如下呼叫
import webpack from "webpack";
var webpack = require("webpack");
"
建議安裝淘寶的npm鏡像,這樣下載npm套件會快上很多,具體做法:
// 方式一npm install xx --registry=https://registry.npm.taobao.org/// 方式二:安装淘宝提供的npm工具npm install -g cnpm cnpm install xx// 方式三// 在用户主目录下,找到.npmrc文件,加上下面这段配置registry=https://registry.npm.taobao.org/
3.webpack的基本配置
創建設定檔(webpack.config.js
,執行webpack指令的時候,預設會執行這個檔)
module.export = {entry : 'app.js',output : {path : 'assets/',filename : '[name].bundle.js'},module : {loaders : [// 使用babel-loader解析js或者jsx模块{ test : /\.js|\.jsx$/, loader : 'babel' },// 使用css-loader解析css模块{ test : /\.css$/, loader : 'style!css' },// or another way{ test : /\.css$/, loader : ['style', 'css'] }]}};
說明一:webpack.config. js
預設輸出一個webpack
的設定文件,與CLI
方式呼叫相同,只是更簡單
說明二:執行webpack
指令即可以運行配置,先決條件,全域安裝webpack
,專案安裝各模組loader
#說明三: entry
對應需要打包的入口js
文件,output
對應輸出的目錄以及文件名,module
中的loaders
對應解析各個模組時需要的載入器
一個簡單的範例
basic/app.js
require('./app.css');document.getElementById('container').textContent = 'APP';
basic/app. css
* {margin: 0;padding: 0;}#container {margin: 50px auto;width: 50%;height: 200px;line-height: 200px;border-radius: 5px;box-shadow: 0 0 .5em #000;text-align: center;font-size: 40px;font-weight: bold;}
basic/webpack.config.js
/** * webpack打包配置文件 */module.exports = {// 如果你有多个入口js,需要打包在一个文件中,那么你可以这么写 // entry : ['./app1.js', './app2.js']entry : './app.js',output : {path : './assets/',filename : '[name].bundle.js'},module : {loaders : [{ test : /\.js$/, loader : 'babel' },{ test : /\.css$/, loader : 'style!css' }]}};
basic/index.html
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>basic webpack</title></head><body><div id="container"></div><script src="./assets/main.bundle.js?1.1.11"></script></body></html>
在basic
資料夾執行webpack
,打包資訊如下
產生main.bundle.js
文件,chunk
名稱為main
,也是webpack
默認產生的chunk
名
## 4. webapck常用到的各點拆分
4.1 entry相關4.1 .1
webpack的多入口配置
entry : {app1 : './app1.js',app2 : './app2.js'}
在
multi-entry資料夾執行
webpack
可見產生了兩個入口文件,以及各自對應的
chunk
# 4.2 output相關4.2.1 output.publicPath
output: {path: "/home/proj/cdn/assets/[hash]",publicPath: "http://cdn.example.com/assets/[hash]/"}
引用一段官網的話:tags or reference assets like images, publicfile is used as the href or url() to the file when it's different then their location on disk (as specified by path).
The publicPath specifies the public URL address of the output files when referenced in a browser. For loaders that embed
<script>
or
#大致上是:
指定了你在瀏覽器中用什麼位址來引用你的靜態文件,它會包括你的圖片、腳本以及樣式加載的地址,一般用於線上發布以及CDN部署的時候使用。
var path = require('path');var HtmlWebpackPlugin = require('html-webpack-plugin');module.exports = {entry : './app.js',output : {path : './assets/',filename : '[name].bundle.js',publicPath : 'http://rynxiao.com/assets/'},module : {loaders : [{ test : /\.js$/, loader : 'babel' },{ test : /\.css$/, loader : 'style!css' }]},plugins : [new HtmlWebpackPlugin({filename: './index-release.html',template: path.resolve('index.template'),inject: 'body'}) ]};
其中我将publicPath
设置成了,其中设置到了插件的一些东西,这点下面会讲到,总之这个插件的作用是生成了上线发布时候的首页文件,其中script
中引用的路径将会被替换。如下图:
4.2.2 output.chunkFilename
各个文件除了主模块以外,还可能生成许多额外附加的块,比如在模块中采用代码分割就会出现这样的情况。其中chunkFilename
中包含以下的文件生成规则:
[id] 会被对应块的id替换.
[name] 会被对应块的name替换(或者被id替换,如果这个块没有name).
[hash] 会被文件hash替换.
[chunkhash] 会被块文件hash替换.
例如,我在output中如下设置:
output : {path : './assets/',filename : '[name].[hash].bundle.js',chunkFilename: "chunk/[chunkhash].chunk.js?1.1.11"}
同时我修改了一下basic/app.js
中的文件
require('./app.css');require.ensure('./main.js', function(require) {require('./chunk.js');});document.getElementById("container").textContent = "APP";
其中对应的chunk.js
就会生成带有chunkhash
的chunk
文件,如下图:
这在做给文件打版本号的时候特别有用,当时如何进行hash
替换,下面会讲到
4.2.3 output.library
这个配置作为库发布的时候会用到,配置的名字即为库的名字,通常可以搭配libraryTarget
进行使用。例如我给basic/webpack.config.js
加上这样的配置:
output : {// ...library : 'testLibrary'// ...}
那么实际上生成出来的main.bundle.js
中会默认带上以下代码:
var testLibrary = (//....以前的打包生成的代码);// 这样在直接引入这个库的时候,就可以直接使用`testLibrary`这个变量
4.2.4 output.libraryTarget
规定了以哪一种方式输出你的库,比如:amd/cmd/或者直接变量,具体包括如下
"var"
- 以直接变量输出(默认library方式) var Library = xxx (default)
"this"
- 通过设置this
的属性输出 this["Library"] = xxx
"commonjs"
- 通过设置exports
的属性输出 exports["Library"] = xxx
"commonjs2"
- 通过设置module.exports
的属性输出 module.exports = xxx
"amd"
- 以amd方式输出
"umd"
- 结合commonjs2/amd/root
例如我以umd
方式输出,如图:
### 4.3 module相关
4.3.1 loader
中!
代表的含义
require("!style!css!less!bootstrap/less/bootstrap.less");
// => the file "bootstrap.less" in the folder "less" in the "bootstrap"
// module (that is installed from github to "node_modules") is
// transformed by the "less-loader". The result is transformed by the
// "css-loader" and then by the "style-loader".
// If configuration has some transforms bound to the file, they will not be applied.
代表加载器的流式调用,例如:
{ test : /\.css|\.less$/, loader : 'style!css!less' }
就代表了先使用less加载器来解释less文件,然后使用css加载器来解析less解析后的文件,依次类推
4.3.2 loaders
中的include
与exclude
include
表示必须要包含的文件或者目录,而exclude
的表示需要排除的目录
比如我们在配置中一般要排除node_modules
目录,就可以这样写
{ test : /\.js$/, loader : 'babel',exclude : nodeModuleDir }
官方建议:优先采用include,并且include最好是文件目录
4.3.3 module.noParse
使用了noParse
的模块将不会被loaders
解析,所以当我们使用的库如果太大,并且其中不包含require
、define
或者类似的关键字的时候(因为这些模块加载并不会被解析,所以就会报错),我们就可以使用这项配置来提升性能。
例如下面的例子:在basic/
目录中新增no-parse.js
var cheerio = require('cheerio');module.exports = function() {console.log(cheerio);}
webpack.config.js
中新增如下配置:
module : {loaders : [{ test : /\.js$/, loader : 'babel' },{ test : /\.css$/, loader : 'style!css' }],noParse : /no-parse.js/}
当执行打包后,在浏览器中打开index.html
时,就会报错require is not defined
4.4 resolve相关
4.4.1 resolve.alias
为模块设置别名,能够让开发者指定一些模块的引用路径。对一些经常要被import或者require的库,如react,我们最好可以直接指定它们的位置,这样webpack可以省下不少搜索硬盘的时间。
例如我们修改basic/app.js
中的相关内容:
var moment = require("moment");document.getElementById("container").textContent = moment().locale('zh-cn').format('LLLL');
加载一个操作时间的类库,让它显示当前的时间。使用webpack --profile --colors --display-modules
执行配置文件,得到如下结果:
其中会发现,打包总共生成了104个隐藏文件,其中一半的时间都在处理关于moment
类库相关的事情,比如寻找moment
依赖的一些类库等等。
在basic/webpack.config.js
加入如下配置,然后执行配置文件
resolve : {alias : {moment : 'moment/min/moment-with-locales.min.js'}}
有没有发现打包的时间已经被大大缩短,并且也只产生了两个隐藏文件。
配合module.noParse
使用
module.noParse
参看上面的解释
noParse: [/moment-with-locales/]
执行打包后,效果如下:
是不是发现打包的时间进一步缩短了。
配合externals
使用
externals
参看下面的解释
Webpack 是如此的强大,用其打包的脚本可以运行在多种环境下,Web 环境只是其默认的一种,也是最常用的一种。考虑到 Web 上有很多的公用 CDN 服务,那么 怎么将 Webpack 和公用的 CDN 结合使用呢?方法是使用 externals 声明一个外部依赖。
externals: {moment: true}
当然了 HTML 代码里需要加上一行
<script src="//apps.bdimg.com/libs/moment/2.8.3/moment-with-locales.min.js?1.1.11"></script>
执行打包后,效果如下:
4.4.2 resolve.extensions
resolve : {extensions: ["", ".webpack.js?1.1.11", ".web.js?1.1.11", ".js?1.1.11", ".less"]}
这项配置的作用是自动加上文件的扩展名,比如你有如下代码:
require('style.less');var app = require('./app.js');
那么加上这项配置之后,你可以写成:
require('style');var app = require('./app');
4.5 externals
当我们想在项目中require一些其他的类库或者API,而又不想让这些类库的源码被构建到运行时文件中,这在实际开发中很有必要。此时我们就可以通过配置externals参数来解决这个问题:
//webpack.config.jsmodule.exports = {externals: { 'react': 'React'},//...}
externals对象的key是给require时用的,比如require('react'),对象的value表示的是如何在global(即window)中访问到该对象,这里是window.React。
同理jquery的话就可以这样写:'jquery': 'jQuery',那么require('jquery')即可。
HTML中注意引入顺序即可:
<script src="react.min.js?1.1.11" /><script src="bundle.js?1.1.11" />
4.6 devtool
提供了一些方式来使得代码调试更加方便,因为打包之后的代码是合并以后的代码,不利于排错和定位。其中有如下几种方式,参见官网devtool
例如,我在basic/app.js
中增加如下配置:
require('./app.css');// 新增hello.js,显然在文件夹中是不会存在hello.js文件的,这里会报错require('./hello.js');document.getElementById("container").textContent = "APP";
执行文件,之后运行index.html
,报错结果如下:
给出的提示实在main.bundle.js第48行,点进去看其中的报错如下:
从这里你完全看不出到底你程序的哪个地方出错了,并且这里的行数还算少,当一个文件出现了上千行的时候,你定位bug
的时间将会更长。
增加devtool
文件配置,如下:
module.exports = {devtool: 'eval-source-map',// ....};
执行文件,之后运行index.html
,报错结果如下:
这里发现直接定位到了app.js
,并且报出了在第二行出错,点击去看其中的报错如下:
发现问题定位一目了然。
5. webpack常用技巧
### 5.1 代码块划分
5.1.1 Commonjs采用require.ensure
来产生chunk
块
require.ensure(dependencies, callback);//static importsimport _ from 'lodash'// dynamic importsrequire.ensure([], function(require) { let contacts = require('./contacts')})
这一点在output.chunkFileName
中已经做过演示,可以去查看
5.1.2 AMD采用require
来产生chunk
块
require(["module-a", "module-b"], function(a, b) {// ...});
5.1.3 将项目APP代码与公共库文件单独打包
我们在basic/app.js
中添加如下代码
var $ = require('juqery'),_ = require('underscore');//.....
然后我们在配置文件中添加vendor
,以及运用代码分离的插件对生成的vendor
块重新命名
var webpack = require("webpack");module.exports = {entry: {app: "./app.js?1.1.11",vendor: ["jquery", "underscore", ...],},output: {filename: "bundle.js?1.1.11"},plugins: [new webpack.optimize.CommonsChunkPlugin(/* chunkName= */"vendor", /* filename= */"vendor.bundle.js?1.1.11") ]};
运行配置文件,效果如下:
5.1.4 抽取多入口文件的公共部分
我们重新建立一个文件夹叫做common
,有如下文件:
// common/app1.jsconsole.log("APP1");
// common/app2.jsconsole.log("APP2");
打包之后生成的app1.bundle.js
、app2.bundle.js
中会存在许多公共代码,我们可以将它提取出来。
// common/webpack.config.js/** * webpack打包配置文件 * 抽取公共部分js */var webpack = require('webpack');module.exports = {entry : {app1 : './app1.js',app2 : './app2.js'},output : {path : './assets/',filename : '[name].bundle.js'},module : {loaders : [{ test : /\.js$/, loader : 'babel' },{ test : /\.css$/, loader : 'style!css' }]},plugins : [new webpack.optimize.CommonsChunkPlugin("common.js?1.1.11") ]};
抽取出的公共js为common.js
,如图
查看app1.bundle.js
,发现打包的内容基本是我们在模块中所写的代码,公共部分已经被提出到common.js
中去了
5.1.5 抽取css文件,打包成css bundle
默认情况下以require('style.css')
情况下导入样式文件,会直接在index.html
的<head>
中生成<style>
标签,属于内联。如果我们想将这些css文件提取出来,可以按照下面的配置去做。
// extract-css/app1.jsrequire('./app1.css');document.getElementById("container").textContent = "APP";// extract-css/app2.jsrequire('./app2.css');document.getElementById("container").textContent = "APP1 APP2";// extract-css/app1.css* {margin: 0;padding: 0;}#container {margin: 50px auto;width: 50%;height: 200px;line-height: 200px;border-radius: 5px;box-shadow: 0 0 .5em #000;text-align: center;font-size: 40px;font-weight: bold;}// extract-css/app2.css#container {background-color: #f0f0f0;}// extract-css/webpack.config.js/** * webpack打包配置文件 * 抽取公共样式(没有chunk) */var webpack = require('webpack');var ExtractTextPlugin = require("extract-text-webpack-plugin");module.exports = {entry : {app1 : './app1.js',app2 : './app1.js'},output : {path : './assets/',filename : '[name].bundle.js'},module : {loaders : [{ test : /\.js$/, loader : 'babel' },{ test : /\.css$/, loader : ExtractTextPlugin.extract("style-loader", "css-loader") }]},plugins : [new ExtractTextPlugin("[name].css?1.1.11") ]};
得到的效果如下图:
如果包含chunk文件,并且chunk文件中也因为了样式文件,那么样式文件会嵌入到js中
css合并到一个文件
// ...module.exports = {// ...plugins: [new ExtractTextPlugin("style.css?1.1.11", {allChunks: true}) ]}
效果如图:
如果包含chunk文件,并且chunk文件中也因为了样式文件,样式文件不会嵌入到js中,而是直接输出到style.css
配合CommonsChunkPlugin一起使用
// ...module.exports = {// ...plugins: [new webpack.optimize.CommonsChunkPlugin("commons", "commons.js?1.1.11"),new ExtractTextPlugin("[name].css?1.1.11") ]}
效果图如下:
5.2 如何给文件打版本
线上发布时为了防止浏览器缓存静态资源而改变文件版本,这里提供两种做法:
5.2.1 使用HtmlWebpackPlugin
插件
// version/webpack.config.js/** * webpack打包配置文件 * 文件打版本,线上发布 */var path = require('path');var HtmlWebpackPlugin = require('html-webpack-plugin');module.exports = {entry : './app.js',output : {path : './assets/',filename : '[name].[hash].bundle.js',publicPath : 'http://rynxiao.com/assets/'},module : {loaders : [{ test : /\.js$/, loader : 'babel' },{ test : /\.css$/, loader : 'style!css' }]},plugins : [new HtmlWebpackPlugin({filename: './index-release.html',template: path.resolve('index.template'),inject: 'body'}) ]};
生成的效果如下:
每次打包之后都会生成文件hash,这样就做到了版本控制
5.2.2 自定义插件给文件添加版本
// version/webpack.config.version.js/** * webpack打包配置文件 * 文件打版本,线上发布,自定义插件方式 */var path = require('path');var fs = require('fs');var cheerio = require('cheerio');module.exports = {entry : './app.js',output : {path : './assets/',filename : '[name].[hash].bundle.js',publicPath : 'http://rynxiao.com/assets/'},module : {loaders : [{ test : /\.js$/, loader : 'babel' },{ test : /\.css$/, loader : 'style!css' }]},plugins : [function() {this.plugin("done", function(stats) {fs.writeFileSync(path.join(__dirname, "stats.json"),JSON.stringify(stats.toJson()) );fs.readFile('./index.html', function(err, data) {var $ = cheerio.load(data.toString()); $('script[src*=assets]').attr('src','http://rynxiao.com/assets/main.' + stats.hash +'.bundle.js');fs.writeFile('./index.html', $.html(), function(err) {!err && console.log('Set has success: '+ stats.hash)})})});}]};
效果如图:
可以达到同样的效果,但是stats暂时只能拿到hash值,因为我们只能考虑在hash上做版本控制,比如我们可以建hash目录等等
5.3 shim
比如有如下场景:我们用到 Pen 这个模块, 这个模块对依赖一个 window.jQuery, 可我手头的 jQuery 是 CommonJS 语法的,而 Pen 对象又是生成好了绑在全局的, 可是我又需要通过 require('pen') 获取变量。 最终的写法就是做 Shim 处理直接提供支持:
做法一:
{test: require.resolve('jquery'), loader: 'expose?jQuery'}, // 输出jQuery到全局{test: require.resolve('pen'), loader: 'exports?window.Pen'} // 将Pen作为一个模块引入
做法二:
new webpack.ProvidePlugin({$: "jquery",jQuery: "jquery","window.jQuery": "jquery"})
This plugin makes a module available as variable in every module.
The module is required only if you use the variable.
Example: Make $ and jQuery available in every module without writing require("jquery").
5.4 怎样写一个loader
Loader 是支持链式执行的,如处理 sass 文件的 loader,可以由 sass-loader、css-loader、style-loader 组成,由 compiler 对其由右向左执行,第一个 Loader 将会拿到需处理的原内容,上一个 Loader 处理后的结果回传给下一个接着处理,最后的 Loader 将处理后的结果以 String 或 Buffer 的形式返回给 compiler。固然也是希望每个 loader 只做该做的事,纯粹的事,而不希望一箩筐的功能都集成到一个 Loader 中。
官网给出了两种写法:
// Identity loadermodule.exports = function(source) { return source;};
// Identity loader with SourceMap supportmodule.exports = function(source, map) { this.callback(null, source, map);};
第一种为基础的写法,采用return
返回, 是因为是同步类的 Loader 且返回的内容唯一。如果你写loader有依赖的话,同样的你也可以在头部进行引用,比如:
// Module dependencies.var fs = require("fs");module.exports = function(source) { return source;};
而第二种则是希望多个loader
之间链式调用,将上一个loader
返回的结果传递给下一个loader
。
案例
比如我想开发一个es6-loader,专门用来做以.es6
文件名结尾的文件处理,那么我们可以这么写
// loader/es6-loader.js// 当然如果我这里不想将这个loader所返回的东西传递给下一个laoder,那么我// 可以在最后直接返回return source// 这里改变之后,我直接可以扔给babel-loader进行处理module.exports = function(source, map) {// 接收es6结尾文件,进行source改变source = "console.log('I changed in loader');"// 打印传递进来的参数console.log("param", this.query);// ... 我们还可以做一些其他的逻辑处理this.callback(null, source, map);};// loader/loader1.es6let a = 1;console.log(a);// loader/app.js// 向loader中传递参数require('./es6-loader?param1=p1!./loader1.es6');document.getElementById("container").textContent = "APP";
执行webpack打包命令,在控制台会打印出param的值,如图:
在执行完成之后,打开index.html
,在控制台打印出“I changed in loader”,而不是1
进阶
可以去阅读以下这篇文章 如何开发一个 Webpack loader
5.4 怎样写一个plugin
插件基本的结构
插件是可以实例化的对象,在它的prototype上必须绑定一个apply
方法。这个方法会在插件安装的时候被Webpack compiler
进行调用。
function HelloWorldPlugin(options) {// Setup the plugin instance with options...}HelloWorldPlugin.prototype.apply = function(compiler) {compiler.plugin('done', function() {console.log('Hello World!'); });};module.exports = HelloWorldPlugin;
安装一个插件,将其添加到配置中的plugins
数组中。
var HelloWorldPlugin = require('hello-world');var webpackConfig = {// ... config settings here ...plugins: [new HelloWorldPlugin({options: true}) ]};
执行效果如图:
这里只作简单的引入,平常一般都不需要自己写插件,如果想进一步了解,可以去看官网例子
5.5 布置一个本地服务器
// 1.全局安装webpack-dev-servercnpm install -g webpack-dev-server// 2. 设置一个文件启动目录,运行webpack-dev-server --content-base basic/// 3. 在浏览器输入localhost:8080
5.6 热替换
// auto-refresh/app.jsdocument.getElementById("container").textContent = "APP APP HOT ";console.log("OK");// auto-refresh/server.jsvar webpack = require('webpack');var config = require('./webpack.config.js');var WebpackDevServer = require("webpack-dev-server");var compiler = webpack(config);new WebpackDevServer(webpack(config), {publicPath: config.output.publicPath,hot: true,noInfo: false,historyApiFallback: true}).listen(8080, 'localhost', function (err, result) {if (err) {console.log(err);}console.log('Listening at localhost:3000');});// auto-refresh/webpack.config.js/** * webpack打包配置文件 */var webpack = require('webpack');module.exports = {entry : ['webpack-dev-server/client?http://127.0.0.1:8080', // WebpackDevServer host and port'webpack/hot/only-dev-server','./app.js'],output : {path : './assets/',filename : '[name].bundle.js',publicPath : './assets/'},module : {loaders : [{ test : /\.js$/, loader : 'react-hot!babel' },{ test : /\.css$/, loader : 'style!css' }]},plugins : [new webpack.HotModuleReplacementPlugin(),new webpack.NoErrorsPlugin(),new webpack.DefinePlugin({'process.env.NODE_ENV': '"development"'}),]};// auto-refresh/index.html<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>basic webpack</title></head><body><div id="container"></div> <script src="./assets/main.bundle.js?1.1.11"></script></body></html>// 运行node server.js// 浏览器输入:localhost:8080
5.7 让wepack.config.js支持es6写法
// 1. 安装babel-core、babel-preset-es2015以及babel-loader// 2. 项目根目录下配置.babelrc文件{ "presets": ["es2015"]}// 3. 将webpack.config.js重新命名为webpack.config.babel.js// 4.运行webpack --config webpack.config.babel.js// 说明node 版本5.0以上,babel-core版本6以上需要如此配置
这是一个 Webpack 支持,但文档里完全没有提到的特性 (应该马上就会加上)。只要你把配置文件命名成 webpack.config.[loader].js ,Webpack 就会用相应的 loader 去转换一遍配置文件。所以要使用这个方法,你需要安装 babel-loader 和 babel-core 两个包。记住你不需要完整的 babel 包。
其他办法(未成功)
1.在上述的方案中,其实不需要重新命名就可以直接运行webpack,但是今天试了一直不成功2.{ test : /\.js|jsx$/, loader : 'babel',query: { //添加两个presents 使用这两种presets处理js或者jsx文件 presets: ['es2015', 'react']} }
6.相关链接
webpack官方网站
用 ES6 编写 Webpack 的配置文件
一小时包教会 —— webpack 入门指南
Webpack傻瓜式指南(一)
前端模块化工具-webpack
如何开发一个 Webpack Loader ( 一 )
关于externals解释
webpack使用优化
http://webpack.github.io/docs/installation.html
以上是webpack基礎入門知道教程的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

隨著網路技術的不斷發展,Web開發技術也不斷更新迭代。 PHP作為一種開源的程式語言,在Web開發中擁有廣泛的應用。而PHP框架作為PHP開發常用的工具之一,能夠提升開發效率與程式碼品質。本文將為大家介紹一個PHP框架-CakePHP,並提供一些簡單入門的教學。一、什麼是CakePHP? CakePHP是一個基於MVC(Model-View-Control

Caddy簡介Caddy是一款功能強大,擴展性高的Web伺服器,目前在Github上已有38K+Star。 Caddy採用Go語言編寫,可用於靜態資源託管和反向代理。 Caddy具有以下主要特性:比較Nginx複雜的配置,其獨創的Caddyfile配置非常簡單;可以透過其提供的AdminAPI實現動態修改配置;預設支援自動化HTTPS配置,能自動申請HTTPS憑證並進行配置;能夠擴展到數以萬計的站點;可以在任意地方執行,沒有額外的依賴;採用Go語言編寫,內存安全更有保證。安裝首先我們直接在CentO

防擋臉彈幕,即大量彈幕飄過,但不會遮擋視訊畫面中的人物,看起來像是從人物背後飄過去的。機器學習已經火了好幾年了,但很多人都不知道瀏覽器中也能運行這些能力;本文介紹在視頻彈幕方面的實踐優化過程,文末列舉了一些本方案可適用的場景,期望能開啟一些腦洞。 mediapipeDemo(https://google.github.io/mediapipe/)展示主流防擋臉彈幕實現原理點播up上傳視訊伺服器後台計算提取視訊畫面中的人像區域,轉換成svg儲存用戶端播放視訊的同時,從伺服器下載svg與彈幕合成,人像

首先你會有個疑惑,frp是什麼呢?簡單的說frp就是內網穿透工具,配置客戶端以後,可以透過伺服器來存取內部網路。現在我的伺服器,已經用nginx做站了,80端口只有一個,那如果frp的服務端也想使用80端口,那該怎麼辦呢?經過查詢,這個是可以實現的,就是利用nginx的反向代理來實現。補充一下:frps就是伺服器端(server),frpc就是客戶端(client)。第一步:修改伺服器中nginx.conf設定檔在nginx.conf中http{}裡加入以下參數,server{listen80

JavaAPI開發中使用Jetty7進行Web伺服器處理隨著互聯網的發展,Web伺服器已經成為了應用程式開發的核心部分,同時也是許多企業所關注的焦點。為了滿足日益增長的業務需求,許多開發人員選擇使用Jetty進行Web伺服器開發,其靈活性和可擴展性受到了廣泛的認可。本文將介紹如何在JavaAPI開發中使用Jetty7進行We

簡明易懂的MyBatis入門教學:一步一步來寫你的第一個程式MyBatis是一種流行的Java持久層框架,它簡化了與資料庫互動的過程。本教學將為您介紹如何使用MyBatis建立和執行簡單的資料庫操作。第一步:環境建置首先,確保您的Java開發環境已經安裝好。然後,下載MyBatis的最新版本,並將其新增至您的Java專案。您可以從MyBatis的官方網站下

表單驗證是Web應用程式開發中非常重要的環節,它能夠在提交表單資料之前對資料進行有效性檢查,避免應用程式出現安全漏洞和資料錯誤。使用Golang可以輕鬆實現網頁應用程式的表單驗證,本文將介紹如何使用Golang來實作網頁應用程式的表單驗證。一、表單驗證的基本要素在介紹如何實作表單驗證之前,我們需要知道表單驗證的基本要素是什麼。表單元素:表單元素是指

Web標準是一組由W3C和其他相關組織制定的規範和指南,它包括HTML、CSS、JavaScript、DOM、Web可訪問性和性能優化等方面的標準化,透過遵循這些標準,可以提高頁面的兼容性、可訪問性、可維護性和效能。 Web標準的目標是使Web內容能夠在不同的平台、瀏覽器和裝置上一致地展示和交互,提供更好的使用者體驗和開發效率。
