목차
1. 소개
1.1 webpack이란
1.2 웹팩은 무엇을 할 수 있나요?
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.相关链接
웹 프론트엔드 JS 튜토리얼 웹팩 튜토리얼 시작하기

웹팩 튜토리얼 시작하기

Jul 22, 2017 pm 04:55 PM
web 시작하기 튜토리얼

이 기사의 github 창고 주소: 이 튜토리얼의 모든 코드가 포함되어 있습니다.

【이 글이 잘 작성되었다고 생각하신다면 이 저장소에 별점을 주세요:-D】

1. 소개

1.1 webpack이란

webpack은 모듈 번들러입니다.
webpack은 종속성이 있는 모듈을 가져와 생성합니다. 해당 모듈을 나타내는 정적 자산입니다.

간단히 요약하면 webpack은 모듈 간의 종속성을 처리하고 해당 모듈에 대한 정적 리소스를 생성하는 모듈 패키징 도구입니다.

1.2 웹팩은 무엇을 할 수 있나요?

웹팩 튜토리얼 시작하기

그림에는 여러 정보가 명확하게 반영되어 있습니다.

  • 웹팩은 프로젝트의 모든 정적 파일을 모듈로 처리합니다

  • 모듈 사이에는 일련의 종속성이 있습니다.

  • 다중 페이지 정적 리소스 생성(패키징 후 코드 분할과 관련된 여러 정적 파일 생성)

2. Webpack 설치

  • 전역 설치(전역 호출용): webpack -- config webpack.config.js)

    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.1webpack的多入口配置

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

entry : {app1 : &#39;./app1.js&#39;,app2 : &#39;./app2.js&#39;}
로그인 후 복사

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]/"}
로그인 후 복사

引用一段官网的话:

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

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;})
    ]};
로그인 후 복사

project Installation
"javascript🎜npm install webpack🎜🎜🎜🎜// 다음과 유사한 프로세스 호출🎜" webpack"에서 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</code >기본값 <code>webpack 구성 파일을 출력합니다. 이는 CLI 방법과 동일하지만 더 간단합니다🎜지침 2: webpack 명령 실행 구성, 첫 번째 조건을 실행하려면 전역적으로 webpack을 설치하고 프로젝트에 각 모듈 loader를 설치하세요. 참고 3: entry는 항목에 해당합니다. 패키징해야 하는 js 파일, output은 출력 디렉터리 및 파일 이름에 해당하고 모듈</code의 <code>로더는 >는 각 모듈을 구문 분석하는 데 필요한 로더에 해당합니다🎜🎜 간단한 예🎜🎜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을 실행하면 패키징 정보는 다음과 같습니다🎜🎜여기에 이미지 설명 쓰기🎜🎜main.bundle.js 파일을 생성합니다. 청크 이름은 main이며, webpack이기도 합니다. 기본적으로 생성되는 청크 이름🎜🎜## 4. 일반적으로 사용되는 분할 points in webapck🎜🎜### 4.1 항목 관련🎜🎜4.1.1webpack 다중 항목 구성🎜🎜위 예의 간단한 구성에는 하나만 있습니다. 엔트리 파일인 경우, 한 페이지에 여러 패키징 파일을 로드해야 하거나 여러 페이지에 해당 패키징 파일을 동시에 도입하려는 경우 어떻게 해야 합니까? 🎜🎜
var cheerio = require(&#39;cheerio&#39;);module.exports = function() {console.log(cheerio);}
로그인 후 복사
로그인 후 복사
🎜🎜 multi-entry 폴더의 webpack을 실행하면 패키징 정보는 다음과 같습니다🎜🎜여기에 그림 설명 쓰기🎜🎜두 개의 항목 파일이 생성되고 해당 청크</code)가 발생하는 것을 볼 수 있습니다. > names🎜<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/}
로그인 후 복사
로그인 후 복사
🎜🎜공식 웹사이트에서 인용: 🎜🎜🎜 publicPath는 <script> 또는 <link> 태그나 이미지와 같은 참조 자산을 포함하는 로더의 경우 브라우저에서 참조될 때 출력 파일의 공개 URL 주소를 지정합니다. , 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中引用的路径将会被替换。如下图:

웹팩 튜토리얼 시작하기


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文件,如下图:

웹팩 튜토리얼 시작하기

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


4.2.3 output.library

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

output : {// ...library : &#39;testLibrary&#39;// ...}
로그인 후 복사
로그인 후 복사

那么实际上生成出来的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 : &#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

웹팩 튜토리얼 시작하기

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执行配置文件,得到如下结果:

웹팩 튜토리얼 시작하기

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

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

resolve : {alias : {moment : &#39;moment/min/moment-with-locales.min.js&#39;}}
로그인 후 복사

웹팩 튜토리얼 시작하기

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

配合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(&#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,报错结果如下:

웹팩 튜토리얼 시작하기

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

웹팩 튜토리얼 시작하기

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

增加devtool文件配置,如下:

module.exports = {devtool: &#39;eval-source-map&#39;,// ....};
로그인 후 복사

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

웹팩 튜토리얼 시작하기

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

웹팩 튜토리얼 시작하기

发现问题定位一目了然。

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")
    ]};
로그인 후 복사

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

웹팩 튜토리얼 시작하기


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,如图

웹팩 튜토리얼 시작하기

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

웹팩 튜토리얼 시작하기

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")
    ]};
로그인 후 복사

得到的效果如下图:

웹팩 튜토리얼 시작하기

如果包含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(&#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;})
    ]};
로그인 후 복사

生成的效果如下:

웹팩 튜토리얼 시작하기

每次打包之后都会生成文件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)})})});}]};
로그인 후 복사

效果如图:

웹팩 튜토리얼 시작하기

可以达到同样的效果,但是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的值,如图:

웹팩 튜토리얼 시작하기

在执行完成之后,打开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(&#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})
    ]};
로그인 후 복사

执行效果如图:

웹팩 튜토리얼 시작하기

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

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


위 내용은 웹팩 튜토리얼 시작하기의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 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 Hentai를 무료로 생성하십시오.

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

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

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

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

PHP 구현 프레임워크: CakePHP 입문 튜토리얼 PHP 구현 프레임워크: CakePHP 입문 튜토리얼 Jun 18, 2023 am 09:04 AM

인터넷 기술의 지속적인 발전에 따라 웹 개발 기술도 지속적으로 업데이트되고 반복됩니다. 오픈 소스 프로그래밍 언어인 PHP는 웹 개발에 널리 사용됩니다. PHP 개발에서 일반적으로 사용되는 도구 중 하나인 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 프로젝트에 추가하세요. 마이바티스 공식 홈페이지에서 다운로드 가능합니다.

Nginx 웹 서버 캐디를 사용하는 방법 Nginx 웹 서버 캐디를 사용하는 방법 May 30, 2023 pm 12:19 PM

Caddy 소개 Caddy는 현재 Github에 38,000개 이상의 별이 있는 강력하고 확장성이 뛰어난 웹 서버입니다. Caddy는 Go 언어로 작성되었으며 정적 리소스 호스팅 및 역방향 프록시에 사용할 수 있습니다. Caddy에는 다음과 같은 주요 기능이 있습니다. Nginx의 복잡한 구성에 비해 원래 Caddyfile 구성은 매우 간단합니다. 기본적으로 자동화된 HTTPS 구성을 지원하고 HTTPS 인증서를 자동으로 적용할 수 있습니다. 수만 개의 사이트를 Go 언어로 작성하여 어디서나 실행할 수 있으며 메모리 안전성이 더욱 보장됩니다. 우선 CentO에 직접 설치해보겠습니다.

웹상의 얼굴 차단 공격에 대한 실시간 보호(머신러닝 기반) 웹상의 얼굴 차단 공격에 대한 실시간 보호(머신러닝 기반) Jun 10, 2023 pm 01:03 PM

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

frps 서버와 웹이 포트 80을 공유하도록 nginx를 구성하는 방법 frps 서버와 웹이 포트 80을 공유하도록 nginx를 구성하는 방법 Jun 03, 2023 am 08:19 AM

우선, frp가 무엇인지에 대해 의문이 생길 것입니다. 간단히 말해서, frp는 인트라넷 침투 도구입니다. 클라이언트를 구성한 후 서버를 통해 인트라넷에 액세스할 수 있습니다. 이제 내 서버는 nginx를 웹 사이트로 사용했으며 포트 80은 하나만 있습니다. FRP 서버도 포트 80을 사용하려면 어떻게 해야 합니까? 쿼리 후에는 nginx의 역방향 프록시를 사용하여 이를 수행할 수 있습니다. 추가하려면: frps는 서버이고 frpc는 클라이언트입니다. 1단계: 서버에서 nginx.conf 구성 파일을 수정하고 nginx.conf의 http{}에 다음 매개변수를 추가합니다. server{listen80

Java API 개발에서 웹 서버 처리를 위해 Jetty7 사용 Java API 개발에서 웹 서버 처리를 위해 Jetty7 사용 Jun 18, 2023 am 10:42 AM

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

Golang을 사용하여 웹 애플리케이션에 대한 양식 유효성 검사를 구현하는 방법 Golang을 사용하여 웹 애플리케이션에 대한 양식 유효성 검사를 구현하는 방법 Jun 24, 2023 am 09:08 AM

양식 유효성 검사는 웹 애플리케이션 개발에서 매우 중요한 링크로, 애플리케이션의 보안 취약성과 데이터 오류를 방지하기 위해 양식 데이터를 제출하기 전에 데이터의 유효성을 확인할 수 있습니다. Golang을 사용하여 웹 애플리케이션에 대한 양식 유효성 검사를 쉽게 구현할 수 있습니다. 이 기사에서는 Golang을 사용하여 웹 애플리케이션에 대한 양식 유효성 검사를 구현하는 방법을 소개합니다. 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