目次
1. はじめに
1.1 webpack とは
3. webpack的基本配置
## 4. webapck常用到的各点拆分
### 4.1 entry相关
### 4.2 output相关
### 4.3 module相关
4.3.1 loader!代表的含义
4.3.2 loaders中的includeexclude
4.3.3 module.noParse
4.4 resolve相关
4.4.1 resolve.alias
4.4.2 resolve.extensions
4.5 externals
4.6 devtool
5. webpack常用技巧
### 5.1 代码块划分
5.2 如何给文件打版本
5.3 shim
5.4 怎样写一个loader
5.4 怎样写一个plugin
5.5 布置一个本地服务器
5.6 热替换
5.7 让wepack.config.js支持es6写法
6.相关链接

Webpack チュートリアルを始める

Jul 22, 2017 pm 04:55 PM
web 入門チュートリアル

この記事の github ウェアハウス アドレス: 、このチュートリアルのすべてのコードが含まれています。

【この記事がよく書かれていると思われる場合は、このリポジトリに星を付けてください:-D】

1. はじめに

1.1 webpack とは

webpack はモジュール バンドラーです。
webpack は依存関係のあるモジュールを受け取り、簡単にまとめると、webpack はモジュール間の依存関係を処理し、対応するモジュールの静的リソースを生成するモジュール パッケージング ツールです。

1.2 webpack でできること

この図にはいくつかの情報が明確に反映されています: Webpack チュートリアルを始める

webpack はプロジェクト内のすべての静的ファイルをモジュールとして扱います
  • モジュール間には一連の依存関係があります
  • 複数ページの静的リソースの生成 (コード分割を伴う、パッケージ化後に複数の静的ファイルが生成されます)
  • 2. Webpack のインストール

グローバル インストール (グローバル呼び出し用) : webpack など -- config webpack.config.js)
  • npm install -g webpack
    ログイン後にコピー

    webpack --config webpack.config.js)

    // 方式一npm install xx --registry=https://registry.npm.taobao.org/// 方式二:安装淘宝提供的npm工具npm install -g cnpm
    cnpm install xx// 方式三// 在用户主目录下,找到.npmrc文件,加上下面这段配置registry=https://registry.npm.taobao.org/
    ログイン後にコピー
  • 项目安装
    "javascript
    npm install webpack

// 处理类似如下调用
import webpack from "webpack";
var webpack = require("webpack");
"

建议安装淘宝的npm镜像,这样下载npm包会快上很多,具体做法:

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'] }]}};
ログイン後にコピー

3. webpack的基本配置

创建配置文件(webpack.config.js,执行webpack命令的时候,默认会执行这个文件)

require('./app.css');document.getElementById('container').textContent = 'APP';
ログイン後にコピー

说明一: webpack.config.js默认输出一个webpack的配置文件,与CLI方式调用相同,只是更加简便
说明二: 执行webpack命令即可以运行配置,先决条件,全局安装webpack,项目安装各模块loader
说明三: entry对应需要打包的入口js文件,output对应输出的目录以及文件名,module中的loaders对应解析各个模块时需要的加载器

一个简单的例子

basic/app.js

* {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/app.css

/** * 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/webpack.config.js

<!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/index.html

entry : {app1 : &#39;./app1.js&#39;,app2 : &#39;./app2.js&#39;}
ログイン後にコピー

basic文件夹执行webpack,打包信息如下

Webpack チュートリアルを始める

生成main.bundle.js文件,chunk名称为main,也是webpack默认生成的chunk

## 4. webapck常用到的各点拆分

### 4.1 entry相关

4.1.1webpack的多入口配置

上例的简单配置中,只有一个入口文件,那么如果对应于一个页面需要加载多个打包文件或者多个页面想同时引入对应的打包文件的时候,应该怎么做?

output: {path: "/home/proj/cdn/assets/[hash]",publicPath: "http://cdn.example.com/assets/[hash]/"}
ログイン後にコピー

multi-entry文件夹执行webpack,打包信息如下

Webpack チュートリアルを始める

可见生成了两个入口文件,以及各自对应的chunk


### 4.2 output相关

4.2.1 output.publicPath

var path = require(&#39;path&#39;);var HtmlWebpackPlugin =  require(&#39;html-webpack-plugin&#39;);module.exports = {entry : &#39;./app.js&#39;,output : {path : &#39;./assets/&#39;,filename : &#39;[name].bundle.js&#39;,publicPath : &#39;http://rynxiao.com/assets/&#39;},module : {loaders : [{ test : /\.js$/, loader : &#39;babel&#39; },{ test : /\.css$/, loader : &#39;style!css&#39; }]},plugins : [new HtmlWebpackPlugin({filename: &#39;./index-release.html&#39;,template: path.resolve(&#39;index.template&#39;),inject: &#39;body&#39;})
    ]};
ログイン後にコピー

引用一段官网的话:

The publicPath specifies the public URL address of the output files when referenced in a browser. For loaders that embed <script> or <link> tags or reference assets like images, publicPath is used as the href or url() to the file when it’s different then their location on disk (as specified by path).

大致意思就是:publicPath

プロジェクトのインストール

"javascript
npm install webpack
🎜🎜🎜// 次のような呼び出しを処理します🎜import webpack from " webpack";🎜var webpack = require("webpack");🎜"🎜🎜 npm パッケージのダウンロードがより速くなるため、タオバオの npm イメージをインストールすることをお勧めします。具体的な方法:🎜🎜
output : {path : &#39;./assets/&#39;,filename : &#39;[name].[hash].bundle.js&#39;,chunkFilename: "chunk/[chunkhash].chunk.js?1.1.11"}
ログイン後にコピー
ログイン後にコピー
🎜🎜3. webpack の基本構成🎜🎜設定ファイル (webpack.config.js、webpack コマンドを実行すると、このファイルがデフォルトで実行されます)🎜🎜
require(&#39;./app.css&#39;);require.ensure(&#39;./main.js&#39;, function(require) {require(&#39;./chunk.js&#39;);});document.getElementById("container").textContent = "APP";
ログイン後にコピー
ログイン後にコピー
🎜🎜説明 1: webpack.config.js >デフォルト webpack 構成ファイルを出力します。これは CLI メソッドと同じですが、より単純です🎜 手順 2: webpack コマンドを実行します構成を実行するには、最初に条件を設定し、webpack をグローバルにインストールし、プロジェクト内の各モジュール loader をインストールします。 注 3: entry はエントリに対応します。パッケージ化する必要があるファイルの jsoutput は出力ディレクトリとファイル名に対応し、loadersmodule に対応します。 > 各モジュールの解析に必要なローダーに対応します🎜🎜 簡単な例🎜🎜basic/app.js🎜🎜
output : {// ...library : &#39;testLibrary&#39;// ...}
ログイン後にコピー
ログイン後にコピー
🎜
🎜basic/ app.css🎜🎜
var testLibrary = (//....以前的打包生成的代码);// 这样在直接引入这个库的时候,就可以直接使用`testLibrary`这个变量
ログイン後にコピー
ログイン後にコピー
🎜
🎜basic/webpack.config.js🎜🎜
{ test : /\.css|\.less$/, loader : &#39;style!css!less&#39; }
ログイン後にコピー
ログイン後にコピー
🎜
🎜basic/index.html</code >🎜🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>{ test : /\.js$/, loader : &amp;#39;babel&amp;#39;,exclude : nodeModuleDir }</pre><div class="contentsignin">ログイン後にコピー</div></div><div class="contentsignin">ログイン後にコピー</div></div>🎜🎜in<code>basicフォルダーでwebpackを実行すると、パッケージ化情報は次のようになります🎜🎜Webpack チュートリアルを始める🎜🎜main.bundle.js ファイル、 を生成します。チャンクの名前はmainであり、webpack でもあります。デフォルトで生成されるチャンクの名前です🎜🎜## 4. 一般的に使用される分割webapck のポイント🎜🎜### 4.1 エントリ関連🎜🎜4.1.1webpack 複数エントリ構成🎜🎜 上記の例の単純な構成では、エントリは 1 つだけですエントリ ファイルを作成する場合、1 ページに複数のパッケージ ファイルをロードする必要がある場合、または複数のページで対応するパッケージ ファイルを同時に導入したい場合は、どうすればよいでしょうか? 🎜🎜
var cheerio = require(&#39;cheerio&#39;);module.exports = function() {console.log(cheerio);}
ログイン後にコピー
ログイン後にコピー
🎜🎜 multi-entry フォルダー内の webpack を実行します。パッケージ化情報は次のとおりです🎜🎜Webpack チュートリアルを始める🎜🎜 2 つのエントリ ファイルと、それらに対応する chunk</code が生成されていることがわかります。 > 名前🎜<hr />🎜### 4.2 出力関連🎜🎜<strong>4.2.1 <code>output.publicPath🎜🎜
module : {loaders : [{ test : /\.js$/, loader : &#39;babel&#39; },{ test : /\.css$/, loader : &#39;style!css&#39; }],noParse : /no-parse.js/}
ログイン後にコピー
ログイン後にコピー
🎜🎜 公式 Web サイトからの引用: 🎜🎜🎜 publicPath は、ブラウザで参照されるときの出力ファイルのパブリック URL アドレスを指定します。ローダーが <script> タグまたは <link> タグを埋め込んだり、画像などのアセットを参照したりする場合に使用します。 publicPath は、ファイルがディスク上の場所 (パスで指定されたもの) と異なる場合、ファイルへの href または url() として使用されます。🎜🎜🎜大まかに言うと、publicPath は参照に使用するアドレスを指定します。ブラウザ内 画像、スクリプト、スタイル読み込みのアドレスを含む静的ファイルは、通常、オンライン パブリッシングと CDN 展開に使用されます。 🎜🎜たとえば、次のような構成があります: 🎜🎜
var moment = require("moment");document.getElementById("container").textContent = moment().locale(&#39;zh-cn&#39;).format(&#39;LLLL&#39;);
ログイン後にコピー
ログイン後にコピー
🎜

其中我将publicPath设置成了,其中设置到了插件的一些东西,这点下面会讲到,总之这个插件的作用是生成了上线发布时候的首页文件,其中script中引用的路径将会被替换。如下图:

Webpack チュートリアルを始める


4.2.2 output.chunkFilename

各个文件除了主模块以外,还可能生成许多额外附加的块,比如在模块中采用代码分割就会出现这样的情况。其中chunkFilename中包含以下的文件生成规则:

[id] 会被对应块的id替换.

[name] 会被对应块的name替换(或者被id替换,如果这个块没有name).

[hash] 会被文件hash替换.

[chunkhash] 会被块文件hash替换.

例如,我在output中如下设置:

output : {path : &#39;./assets/&#39;,filename : &#39;[name].[hash].bundle.js&#39;,chunkFilename: "chunk/[chunkhash].chunk.js?1.1.11"}
ログイン後にコピー
ログイン後にコピー

同时我修改了一下basic/app.js中的文件

require(&#39;./app.css&#39;);require.ensure(&#39;./main.js&#39;, function(require) {require(&#39;./chunk.js&#39;);});document.getElementById("container").textContent = "APP";
ログイン後にコピー
ログイン後にコピー

其中对应的chunk.js就会生成带有chunkhashchunk文件,如下图:

Webpack チュートリアルを始める

这在做给文件打版本号的时候特别有用,当时如何进行hash替换,下面会讲到


4.2.3 output.library

这个配置作为库发布的时候会用到,配置的名字即为库的名字,通常可以搭配libraryTarget进行使用。例如我给basic/webpack.config.js加上这样的配置:

output : {// ...library : &#39;testLibrary&#39;// ...}
ログイン後にコピー
ログイン後にコピー

那么实际上生成出来的main.bundle.js中会默认带上以下代码:

var testLibrary = (//....以前的打包生成的代码);// 这样在直接引入这个库的时候,就可以直接使用`testLibrary`这个变量
ログイン後にコピー
ログイン後にコピー

Webpack チュートリアルを始める


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方式输出,如图:

Webpack チュートリアルを始める


### 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 : &#39;style!css!less&#39; }
ログイン後にコピー
ログイン後にコピー

就代表了先使用less加载器来解释less文件,然后使用css加载器来解析less解析后的文件,依次类推


4.3.2 loaders中的includeexclude

include表示必须要包含的文件或者目录,而exclude的表示需要排除的目录

比如我们在配置中一般要排除node_modules目录,就可以这样写

{ test : /\.js$/, loader : &#39;babel&#39;,exclude : nodeModuleDir 
}
ログイン後にコピー
ログイン後にコピー

官方建议:优先采用include,并且include最好是文件目录


4.3.3 module.noParse

使用了noParse的模块将不会被loaders解析,所以当我们使用的库如果太大,并且其中不包含requiredefine或者类似的关键字的时候(因为这些模块加载并不会被解析,所以就会报错),我们就可以使用这项配置来提升性能。

例如下面的例子:在basic/目录中新增no-parse.js

var cheerio = require(&#39;cheerio&#39;);module.exports = function() {console.log(cheerio);}
ログイン後にコピー
ログイン後にコピー

webpack.config.js中新增如下配置:

module : {loaders : [{ test : /\.js$/, loader : &#39;babel&#39; },{ test : /\.css$/, loader : &#39;style!css&#39; }],noParse : /no-parse.js/}
ログイン後にコピー
ログイン後にコピー

当执行打包后,在浏览器中打开index.html时,就会报错require is not defined

Webpack チュートリアルを始める

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(&#39;zh-cn&#39;).format(&#39;LLLL&#39;);
ログイン後にコピー
ログイン後にコピー

加载一个操作时间的类库,让它显示当前的时间。使用webpack --profile --colors --display-modules执行配置文件,得到如下结果:

Webpack チュートリアルを始める

其中会发现,打包总共生成了104个隐藏文件,其中一半的时间都在处理关于moment类库相关的事情,比如寻找moment依赖的一些类库等等。

basic/webpack.config.js加入如下配置,然后执行配置文件

resolve : {alias : {moment : &#39;moment/min/moment-with-locales.min.js&#39;}}
ログイン後にコピー

Webpack チュートリアルを始める

有没有发现打包的时间已经被大大缩短,并且也只产生了两个隐藏文件。

配合module.noParse使用

module.noParse参看上面的解释

noParse: [/moment-with-locales/]
ログイン後にコピー

执行打包后,效果如下:

Webpack チュートリアルを始める

是不是发现打包的时间进一步缩短了。

配合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>
ログイン後にコピー

执行打包后,效果如下:

Webpack チュートリアルを始める


4.4.2 resolve.extensions

resolve : {extensions: ["", ".webpack.js?1.1.11", ".web.js?1.1.11", ".js?1.1.11", ".less"]}
ログイン後にコピー

这项配置的作用是自动加上文件的扩展名,比如你有如下代码:

require(&#39;style.less&#39;);var app = require(&#39;./app.js&#39;);
ログイン後にコピー

那么加上这项配置之后,你可以写成:

require(&#39;style&#39;);var app = require(&#39;./app&#39;);
ログイン後にコピー

4.5 externals

当我们想在项目中require一些其他的类库或者API,而又不想让这些类库的源码被构建到运行时文件中,这在实际开发中很有必要。此时我们就可以通过配置externals参数来解决这个问题:

//webpack.config.jsmodule.exports = {externals: {  &#39;react&#39;: &#39;React&#39;},//...}
ログイン後にコピー

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(&#39;./app.css&#39;);// 新增hello.js,显然在文件夹中是不会存在hello.js文件的,这里会报错require(&#39;./hello.js&#39;);document.getElementById("container").textContent = "APP";
ログイン後にコピー

执行文件,之后运行index.html,报错结果如下:

Webpack チュートリアルを始める

给出的提示实在main.bundle.js第48行,点进去看其中的报错如下:

Webpack チュートリアルを始める

从这里你完全看不出到底你程序的哪个地方出错了,并且这里的行数还算少,当一个文件出现了上千行的时候,你定位bug的时间将会更长。

增加devtool文件配置,如下:

module.exports = {devtool: &#39;eval-source-map&#39;,// ....};
ログイン後にコピー

执行文件,之后运行index.html,报错结果如下:

Webpack チュートリアルを始める

这里发现直接定位到了app.js,并且报出了在第二行出错,点击去看其中的报错如下:

Webpack チュートリアルを始める

发现问题定位一目了然。

5. webpack常用技巧

### 5.1 代码块划分

5.1.1 Commonjs采用require.ensure来产生chunk

require.ensure(dependencies, callback);//static importsimport _ from &#39;lodash&#39;// dynamic importsrequire.ensure([], function(require) {
  let contacts = require(&#39;./contacts&#39;)})
ログイン後にコピー

这一点在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(&#39;juqery&#39;),_ = require(&#39;underscore&#39;);//.....
ログイン後にコピー

然后我们在配置文件中添加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")
    ]};
ログイン後にコピー

运行配置文件,效果如下:

Webpack チュートリアルを始める


5.1.4 抽取多入口文件的公共部分

我们重新建立一个文件夹叫做common,有如下文件:

// common/app1.jsconsole.log("APP1");
ログイン後にコピー
// common/app2.jsconsole.log("APP2");
ログイン後にコピー

打包之后生成的app1.bundle.jsapp2.bundle.js中会存在许多公共代码,我们可以将它提取出来。

// common/webpack.config.js/** * webpack打包配置文件 * 抽取公共部分js */var webpack = require('webpack');module.exports = {entry : {app1 : &#39;./app1.js&#39;,app2 : &#39;./app2.js&#39;},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,如图

Webpack チュートリアルを始める

查看app1.bundle.js,发现打包的内容基本是我们在模块中所写的代码,公共部分已经被提出到common.js中去了

Webpack チュートリアルを始める

5.1.5 抽取css文件,打包成css bundle

默认情况下以require(&#39;style.css&#39;)情况下导入样式文件,会直接在index.html<head>中生成<style>标签,属于内联。如果我们想将这些css文件提取出来,可以按照下面的配置去做。

// extract-css/app1.jsrequire(&#39;./app1.css&#39;);document.getElementById("container").textContent = "APP";// extract-css/app2.jsrequire(&#39;./app2.css&#39;);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(&#39;webpack&#39;);var ExtractTextPlugin = require("extract-text-webpack-plugin");module.exports = {entry : {app1 : &#39;./app1.js&#39;,app2 : &#39;./app1.js&#39;},output : {path : &#39;./assets/&#39;,filename : &#39;[name].bundle.js&#39;},module : {loaders : [{ test : /\.js$/, loader : &#39;babel&#39; },{ test : /\.css$/, loader : ExtractTextPlugin.extract("style-loader", "css-loader") }]},plugins : [new ExtractTextPlugin("[name].css?1.1.11")
    ]};
ログイン後にコピー

得到的效果如下图:

Webpack チュートリアルを始める

如果包含chunk文件,并且chunk文件中也因为了样式文件,那么样式文件会嵌入到js中

css合并到一个文件

// ...module.exports = {// ...plugins: [new ExtractTextPlugin("style.css?1.1.11", {allChunks: true})
    ]}
ログイン後にコピー

效果如图:

Webpack チュートリアルを始める

如果包含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")
    ]}
ログイン後にコピー

效果图如下:

Webpack チュートリアルを始める


5.2 如何给文件打版本

线上发布时为了防止浏览器缓存静态资源而改变文件版本,这里提供两种做法:

5.2.1 使用HtmlWebpackPlugin插件

// version/webpack.config.js/** * webpack打包配置文件 * 文件打版本,线上发布 */var path = require(&#39;path&#39;);var HtmlWebpackPlugin =  require(&#39;html-webpack-plugin&#39;);module.exports = {entry : &#39;./app.js&#39;,output : {path : &#39;./assets/&#39;,filename : &#39;[name].[hash].bundle.js&#39;,publicPath : &#39;http://rynxiao.com/assets/&#39;},module : {loaders : [{ test : /\.js$/, loader : &#39;babel&#39; },{ test : /\.css$/, loader : &#39;style!css&#39; }]},plugins : [new HtmlWebpackPlugin({filename: &#39;./index-release.html&#39;,template: path.resolve(&#39;index.template&#39;),inject: &#39;body&#39;})
    ]};
ログイン後にコピー

生成的效果如下:

Webpack チュートリアルを始める

每次打包之后都会生成文件hash,这样就做到了版本控制


5.2.2 自定义插件给文件添加版本

// version/webpack.config.version.js/** * webpack打包配置文件 * 文件打版本,线上发布,自定义插件方式 */var path = require(&#39;path&#39;);var fs = require(&#39;fs&#39;);var cheerio = require(&#39;cheerio&#39;);module.exports = {entry : &#39;./app.js&#39;,output : {path : &#39;./assets/&#39;,filename : &#39;[name].[hash].bundle.js&#39;,publicPath : &#39;http://rynxiao.com/assets/&#39;},module : {loaders : [{ test : /\.js$/, loader : &#39;babel&#39; },{ test : /\.css$/, loader : &#39;style!css&#39; }]},plugins : [function() {this.plugin("done", function(stats) {fs.writeFileSync(path.join(__dirname, "stats.json"),JSON.stringify(stats.toJson())
                );fs.readFile(&#39;./index.html&#39;, function(err, data) {var $ = cheerio.load(data.toString());   $(&#39;script[src*=assets]&#39;).attr(&#39;src&#39;,&#39;http://rynxiao.com/assets/main.&#39; + stats.hash +&#39;.bundle.js&#39;);fs.writeFile(&#39;./index.html&#39;, $.html(), function(err) {!err && console.log(&#39;Set has success: &#39;+ stats.hash)})})});}]};
ログイン後にコピー

效果如图:

Webpack チュートリアルを始める

可以达到同样的效果,但是stats暂时只能拿到hash值,因为我们只能考虑在hash上做版本控制,比如我们可以建hash目录等等


5.3 shim

比如有如下场景:我们用到 Pen 这个模块, 这个模块对依赖一个 window.jQuery, 可我手头的 jQuery 是 CommonJS 语法的,而 Pen 对象又是生成好了绑在全局的, 可是我又需要通过 require('pen') 获取变量。 最终的写法就是做 Shim 处理直接提供支持:

做法一:

{test: require.resolve(&#39;jquery&#39;), loader: &#39;expose?jQuery&#39;}, // 输出jQuery到全局{test: require.resolve(&#39;pen&#39;), loader: &#39;exports?window.Pen&#39;}    // 将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(&#39;I changed in loader&#39;);"// 打印传递进来的参数console.log("param", this.query);// ... 我们还可以做一些其他的逻辑处理this.callback(null, source, map);};// loader/loader1.es6let a = 1;console.log(a);// loader/app.js// 向loader中传递参数require(&#39;./es6-loader?param1=p1!./loader1.es6&#39;);document.getElementById("container").textContent = "APP";
ログイン後にコピー

执行webpack打包命令,在控制台会打印出param的值,如图:

Webpack チュートリアルを始める

在执行完成之后,打开index.html,在控制台打印出“I changed in loader”,而不是1

Webpack チュートリアルを始める

进阶

可以去阅读以下这篇文章 如何开发一个 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(&#39;done&#39;, function() {console.log(&#39;Hello World!&#39;); });};module.exports = HelloWorldPlugin;
ログイン後にコピー

安装一个插件,将其添加到配置中的plugins数组中。

var HelloWorldPlugin = require(&#39;hello-world&#39;);var webpackConfig = {// ... config settings here ...plugins: [new HelloWorldPlugin({options: true})
    ]};
ログイン後にコピー

执行效果如图:

Webpack チュートリアルを始める

这里只作简单的引入,平常一般都不需要自己写插件,如果想进一步了解,可以去看官网例子

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(&#39;webpack&#39;);var config = require(&#39;./webpack.config.js&#39;);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, &#39;localhost&#39;, function (err, result) {if (err) {console.log(err);}console.log(&#39;Listening at localhost:3000&#39;);});// auto-refresh/webpack.config.js/** * webpack打包配置文件 */var webpack = require(&#39;webpack&#39;);module.exports = {entry : [&#39;webpack-dev-server/client?http://127.0.0.1:8080&#39;, // WebpackDevServer host and port&#39;webpack/hot/only-dev-server&#39;,&#39;./app.js&#39;],output : {path : &#39;./assets/&#39;,filename : &#39;[name].bundle.js&#39;,publicPath : &#39;./assets/&#39;},module : {loaders : [{ test : /\.js$/, loader : &#39;react-hot!babel&#39; },{ test : /\.css$/, loader : &#39;style!css&#39; }]},plugins : [new webpack.HotModuleReplacementPlugin(),new webpack.NoErrorsPlugin(),new webpack.DefinePlugin({&#39;process.env.NODE_ENV&#39;: &#39;"development"&#39;}),]};// 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 : &#39;babel&#39;,query: {  //添加两个presents 使用这两种presets处理js或者jsx文件  presets: [&#39;es2015&#39;, &#39;react&#39;]} }
ログイン後にコピー

6.相关链接

webpack官方网站

用 ES6 编写 Webpack 的配置文件

一小时包教会 —— webpack 入门指南

Webpack傻瓜式指南(一)

前端模块化工具-webpack

如何开发一个 Webpack Loader ( 一 )

关于externals解释

webpack使用优化

http://webpack.github.io/docs/installation.html


以上がWebpack チュートリアルを始めるの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

PHP 実装フレームワーク: CakePHP 入門チュートリアル PHP 実装フレームワーク: CakePHP 入門チュートリアル Jun 18, 2023 am 09:04 AM

インターネット技術の継続的な発展に伴い、Web 開発技術も常に更新され、反復されています。 PHP はオープンソース プログラミング言語として、Web 開発で広く使用されています。 PHP 開発で一般的に使用されるツールの 1 つである PHP フレームワークは、開発効率とコード品質を向上させることができます。この記事では、PHP フレームワークである CakePHP を紹介し、始めるための簡単なチュートリアルをいくつか提供します。 1.CakePHPとは何ですか? CakePHP は MVC (Model-View-Control) に基づいたモデルです。

初心者ガイド: ゼロから始めて、MyBatis を段階的に学習します 初心者ガイド: ゼロから始めて、MyBatis を段階的に学習します Feb 19, 2024 am 11:05 AM

簡潔でわかりやすい MyBatis 入門チュートリアル: 最初のプログラムをステップバイステップで作成する MyBatis は、データベースとの対話プロセスを簡素化する人気のある Java 永続層フレームワークです。このチュートリアルでは、MyBatis を使用して簡単なデータベース操作を作成および実行する方法を説明します。ステップ 1: 環境セットアップ まず、Java 開発環境がインストールされていることを確認します。次に、MyBatis の最新バージョンをダウンロードし、Java プロジェクトに追加します。 MyBatisの公式Webサイトからダウンロードできます。

Nginx Webサーバーキャディの使用方法 Nginx Webサーバーキャディの使用方法 May 30, 2023 pm 12:19 PM

Caddy の概要 Caddy は強力で拡張性の高い Web サーバーであり、現在 Github 上に 38,000 以上のスターが付いています。 Caddy は Go 言語で書かれており、静的リソースのホスティングとリバース プロキシに使用できます。 Caddy には以下の主な特徴があります: Nginx の複雑な構成と比較して、元の Caddyfile 構成は非常にシンプルです; 提供する AdminAPI を通じて構成を動的に変更できます; デフォルトで自動 HTTPS 構成をサポートし、自動的に適用して構成できますHTTPS 証明書; 数万のサイトのデータに拡張可能; 追加の依存関係なしでどこでも実行可能; Go 言語で記述されているため、メモリの安全性がより保証されます。まずはCentOに直接インストールします

Java API開発におけるWebサーバー処理にJetty7を使用する Java API開発におけるWebサーバー処理にJetty7を使用する Jun 18, 2023 am 10:42 AM

JavaAPI 開発における Web サーバー処理に Jetty7 を使用する インターネットの発展に伴い、Web サーバーはアプリケーション開発の中核部分となり、多くの企業でも注目を集めています。増大するビジネス ニーズを満たすために、多くの開発者が Web サーバー開発に Jetty の使用を選択しており、その柔軟性と拡張性は広く認識されています。この記事では、JavaAPI 開発における Jetty7 の使用方法を紹介します。

ウェブ上の顔面ブロック攻撃に対するリアルタイム保護 (機械学習に基づく) ウェブ上の顔面ブロック攻撃に対するリアルタイム保護 (機械学習に基づく) Jun 10, 2023 pm 01:03 PM

顔面遮蔽弾幕とは、映像内の人物を遮ることなく大量の弾幕が浮遊し、人物の背後から浮遊しているように見せることです。機械学習は数年前から普及していますが、これらの機能がブラウザでも実行できることは多くの人に知られていません。この記事では、ビデオ連発における実際的な最適化プロセスを紹介します。記事の最後に、適用可能なシナリオをいくつか示します。このソリューションを開くことを望んでいます。いくつかのアイデアがあります。 mediapipeDemo (https://google.github.io/mediapipe/) は、顔ブロック弾幕のオンデマンドアップアップロードの主流の実装原理を示していますサーバーのバックグラウンド計算により、ビデオ画面内のポートレート領域を抽出し、SVG ストレージに変換しますクライアントがビデオを再生している間、サーバーから SVG をダウンロードし、弾幕、ポートレートと組み合わせる

FRPS サーバーと Web がポート 80 を共有するように nginx を設定する方法 FRPS サーバーと Web がポート 80 を共有するように nginx を設定する方法 Jun 03, 2023 am 08:19 AM

まず、frpって何?という疑問があると思います。簡単に言うと、frp はイントラネット侵入ツールであり、クライアントを設定すると、サーバー経由でイントラネットにアクセスできるようになります。現在、私のサーバーは Web サイトとして nginx を使用しており、ポート 80 が 1 つだけあります。では、FRP サーバーもポート 80 を使用したい場合はどうすればよいでしょうか?クエリ後、nginx のリバース プロキシを使用してこれを実現できます。追加: frps はサーバー、frpc はクライアントです。ステップ 1: サーバーの nginx.conf 構成ファイルを変更し、次のパラメータを nginx.conf の http{} に追加します。server{listen80

Golang を使用して Web アプリケーションのフォーム検証を実装する方法 Golang を使用して Web アプリケーションのフォーム検証を実装する方法 Jun 24, 2023 am 09:08 AM

フォーム検証は Web アプリケーション開発において非常に重要なリンクであり、フォーム データを送信する前にデータの有効性をチェックして、アプリケーションのセキュリティ脆弱性やデータ エラーを回避できます。 Web アプリケーションのフォーム検証は、Golang を使用すると簡単に実装できます。この記事では、Golang を使用して Web アプリケーションのフォーム検証を実装する方法を紹介します。 1. フォーム検証の基本要素 フォーム検証の実装方法を紹介する前に、フォーム検証の基本要素が何であるかを知る必要があります。フォーム要素: フォーム要素は

PHP 実装フレームワーク: Lumen フレームワーク入門チュートリアル PHP 実装フレームワーク: Lumen フレームワーク入門チュートリアル Jun 18, 2023 am 08:39 AM

Lumen は、Laravel フレームワーク開発者によって開発された PHP ベースのマイクロフレームワークであり、元々は、Laravel フレームワークのコンポーネントと機能の一部を保持しながら、小さな API アプリケーションとマイクロサービスを迅速に構築するように設計されました。 Lumen フレームワークは軽量で高速で使いやすいため、広く注目され、使用されています。この記事では、Lumen フレームワークを簡単に使い始め、Lumen フレームワークを使用して単純な API アプリケーションを構築する方法を学びます。フレームワークの準備 Lumen フレームワークを学習する前に、次のことを行う必要があります。

See all articles