GVKun编程网logo

深入浅出的webpack构建工具---webpack基本配置(一)(webpack构建流程步骤)

13

以上就是给各位分享深入浅出的webpack构建工具---webpack基本配置(一),其中也会对webpack构建流程步骤进行解释,同时本文还将给你拓展02-webpack的基本配置和输入webpac

以上就是给各位分享深入浅出的webpack构建工具---webpack基本配置(一),其中也会对webpack构建流程步骤进行解释,同时本文还将给你拓展02-webpack的基本配置和输入webpack实现自动打包、2020年你不能不知道的webpack基本配置、webpack 4.x 解决 webpack-dev-server工具在webpack构建的项目中使用问题、webpack devServer 学习笔记(深入浅出webpack目录2.6)等相关知识,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

本文目录一览:

深入浅出的webpack构建工具---webpack基本配置(一)(webpack构建流程步骤)

深入浅出的webpack构建工具---webpack基本配置(一)(webpack构建流程步骤)

深入浅出的webpack构建工具---webpack基本配置(一)

阅读目录

  • 一:webpack入门构建:

    1. 安装webpack到全局

    2. 安装webpack到本项目。

    3. 如何使用webpack?

    4. 使用loader

    5. 使用插件(Plugin)

    6. 使用DevServer

  • 二:webpack基本配置

    1. context

    2. entry

    3. Output

    4. 模式(mode)

    5.理解使用Loader

    6.理解noParse

    7. 理解alias

    8.理解extensions

    9.理解Externals

回到顶部

1. 安装webpack到全局

在学习构建之前,我们来在本地文件新建一个存放项目的文件夹,比如叫demo1这个项目,然后进入demo1该项目的根目录后,执行命令 npm init
运行下,一路回车(先简单的来),就会生成一个package.json文件。

在项目中直接运行如下命令,就可以把webpack安装到全局去;如下命令:

npm install -g webpack
回到顶部

2. 安装webpack到本项目。

在本项目中,执行如下命令,就可以把webpack安装到本地项目中,如下命令:

npm install --save-dev webpack
回到顶部

3. 如何使用webpack?

在编写webpack代码之前,我们先搭建好目录结构如下:

### 目录结构如下:
demo1                                       # 工程名
|   |--- dist                               # 打包后生成的目录文件             
|   |--- node_modules                       # 所有的依赖包
|   |--- js                                 # 存放所有js文件
|   | |-- demo1.js  
|   | |-- main.js                           # js入口文件
|   |
|   |--- webpack.config.js                  # webpack配置文件
|   |--- index.html                         # html文件
|   |--- styles                             # 存放所有的css样式文件                              
|   |--- .gitignore  
|   |--- README.md
|   |--- package.json

index.html代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
  <div id="app"></div>
  <script src="./dist/bundle.js"></script>
</body>
</html>

js/demo1.js 代码假如是如下:

function demo1Func() {
  console.log(11);
};
module.exports = demo1Func;

js/main.js 代码如下:

const demo1Func = require(''./demo1.js'');

demo1Func();

如上的简单的代码,我们先从上面的简单的代码来学起,然后逐渐会慢慢的深入的讲解webpack知识点;我们在项目的根目录中新建 webpack.config.js件;编写配置文件如下:

const path = require(''path'');

module.exports = {
  entry: ''./js/main.js'',

  output: {
    // 将所有依赖的模块合并输出到一个叫bundle.js文件内
    filename: ''bundle.js'',
    // 将输出的文件都放在dist目录下
    path: path.resolve(__dirname, ''./dist'')
  }
};

一切编写文件好了以后,我们一般情况下会在项目的根目录下 运行webpack命令;但是当我们运行webpack后,会报错如下信息:

One CLI for webpack must be installed. These are recommended choices, delivered as separate packages:
 - webpack-cli (https://github.com/webpack/webpack-cli)
   The original webpack full-featured CLI.
 - webpack-command (https://github.com/webpack-contrib/webpack-command)
   A lightweight, opinionated webpack CLI.
We will use "npm" to install the CLI via "npm install -D".
Which one do you like to install (webpack-cli/webpack-command):

因此我们可以在项目的目录下 安装下 webpack-cli ,如下命令安装:

npm install webpack-cli -g

安装完成后,我们再执行webpack命令后,就会在项目中根目录生成dist文件夹,该文件夹内会生成 bundle.js 文件。这时候我们再打开index.html, 运行后,会发现执行了依赖的demo1.js了。

3.1 理解配置文件 entry(入口)和 出口 (output)

入口(entry) 是指示webpack应该使用哪个模块,来作为构建内部依赖js的开始,进入入口起点后,webpack会找出有哪些模块和库是入口js依赖的。
出口(output) 是告诉webpack在什么地方输出它所创建的bundles,以及如何命名这些文件,默认值为 ''./dist''.

回到顶部

4. 使用loader

webpack的构建是一个采用CommonJS规范的模块化项目,现在我们还是继续上面的项目,我们再在main.js会引入一个css文件。因此会在main.js代码修改如下:

require(''../styles/main.css'');

const demo1Func = require(''./demo1.js'');

demo1Func();

然后main.css代码如下:

#app {
  font-size: 18px;
}

如果我们现在直接去执行webpack的话,就会报错,因此我们需要在webpack中加入Loader的机制。将webpack代码改成如下:

const path = require(''path'');

module.exports = {
  entry: ''./js/main.js'',

  output: {
    // 将所有依赖的模块合并输出到一个叫bundle.js文件内
    filename: ''bundle.js'',
    // 将输出的文件都放在dist目录下
    path: path.resolve(__dirname, ''./dist'')
  },
  module: {
    rules: [
      {
        // 用正则去匹配以 .css结尾的文件,然后需要使用loader进行转换
        test: /\.css$/,
        use: [''style-loader'', ''css-loader?minimize'']
      }
    ]
  }
};

如上代码,我们在webpack编译之前需要安装 style-loader 和 css-loader, 如下命令进行安装:

npm install --save-dev style-loader css-loader

如上配置代码中的 module.rules 数组配置了一组规则,是来告诉webpack在遇到哪些文件时使用哪些loader去加载和转换,比如上面的使用test正则去匹配
以 .css 结尾的文件,会先使用 css-loader 读取css文件,然后使用 style-loader将css的内容注入到javascript里面去。

注意:
1. use属性的值是一个使用Loader名称组成的数组,Loader的执行顺序是由后往前的。由于loader有顺序的,因此我们在配置中不能如下编写loader;
代码如下:

module: {
    rules: [
      {
        // 用正则去匹配以 .css结尾的文件,然后需要使用loader进行转换
        test: /\.css$/,
        use: [''css-loader?minimize'', ''style-loader'']
      }
    ]
  }

2. 每个Loader都可以通过 URL queryString 的方式传入参数,比如 css-loader?minimize是告诉css-loader是开启css压缩。

现在我们可以在项目中的根目录运行 webpack命令了,一切正常后,我们打开index.html后,查看代码,发现css被加载到style标签内了;

style-loader的原理:是将css的内容使用javascript的字符串存储起来,在网页执行javascript时通过DOM操作,动态地向HTML head标签里插入 HTML style标签。

3. 配置loader的方式也可以使用Object来实现,比如如上的匹配css代码,可以改成如下:

use: [
    ''style-loader'', 
    {
      loader: ''css-loader'',
      options: {
        minimize: true
      }
    }
] 

因此webpack所有的配置代码变成如下:

const path = require(''path'');
  module.exports = {
    entry: ''./js/main.js'',
    output: {
      // 将所有依赖的模块合并输出到一个叫bundle.js文件内
      filename: ''bundle.js'',
      // 将输出的文件都放在dist目录下
      path: path.resolve(__dirname, ''./dist'')
    },
    module: {
      rules: [
        {
          // 用正则去匹配以 .css结尾的文件,然后需要使用loader进行转换
          test: /\.css$/,
          use: [
            ''style-loader'', 
            {
              loader: ''css-loader'',
              options: {
                minimize: true
              }
            }
          ]
        }
      ]
    }
  };
回到顶部

5. 使用插件(Plugin)

loader的作用是被用于转换某些类型的模块,而插件则可以用于执行范围更广的任务,插件的范围包括,从打包优化和压缩,一直到重新定义环节中的变量。
如果想要使用一个插件,我们只需要require()它,然后把它添加到 plugins数组中。我们可以在一个配置文件中因为不同的目的多次使用用一个插件,因此
我们可以使用new操作符来创建它的实列。

上面我们是通过loader加载了css文件到js中去,下面我们通过plugin将注入的bundle.js文件里的css提取到单独的文件中,我们需要使用到
extract-text-webpack-plugin 插件,配置代码如下:

const path = require(''path'');

// 提取css的插件
const ExtractTextPlugin = require(''extract-text-webpack-plugin'');

module.exports = {
  entry: ''./js/main.js'',

  output: {
    // 将所有依赖的模块合并输出到一个叫bundle.js文件内
    filename: ''bundle.js'',
    // 将输出的文件都放在dist目录下
    path: path.resolve(__dirname, ''./dist'')
  },
  module: {
    rules: [
      {
        // 使用正则去匹配要用该loader转换的css文件
        test: /\.css$/,
        loaders: ExtractTextPlugin.extract({
          // 转换 .css文件需要使用的Loader
          use: [''css-loader'']
        })
      }
    ]
  },
  plugins: [
    new ExtractTextPlugin({
      // 从js文件中提取出来的 .css文件的名称
      filename: `main.css`
    })
  ]
};

要使用 extract-text-webpack-plugin 插件的话,首先我们需要安装该插件,安装插件的命令如下:

npm install --save-dev extract-text-webpack-plugin

当安装成功后,我们需要运行webpack命令后,发现命令行报错了,报错信息如下:

(node:86210) DeprecationWarning: Tapable.plugin is deprecated. Use new API on `.hooks` instead
/usr/local/lib/node_modules/webpack/lib/Chunk.js:802

解决的办法是 安装 extract-text-webpack-plugin 时,需要如下安装,安装命令如下:

npm install extract-text-webpack-plugin@next

安装成功后,再运行webpack就可以了,我们可以看到在dist文件夹内会多一个main.css, 因此我们可以在index.html中把 css文件引入进去即可。

回到顶部

6. 使用DevServer

前面是使用webpack进行打包,但是在开发中我们还需要一个本地文件的服务器,并且当我们保存代码的时候会自动进行打包,并且还支持 Source Map,
以方便代码调试等功能,因此我们现在需要使用到 DevServer了。

首先我们需要安装 webpack-dev-server, 如下安装命令:

npm install --save-dev webpack-dev-server

当然我们还需要全局安装一下,安装命令如下:

npm install webpack-dev-server -g

然后当我们在命令行输入 webpack-dev-server 运行后,发现报错了,报错如下信息:

The CLI moved into a separate package: webpack-cli.
Please install ''webpack-cli'' in addition to webpack itself to use the CLI.
-> When using npm: npm install webpack-cli -D
-> When using yarn: yarn add webpack-cli -D
module.js:471

因此我们需要重新运行下如下命令:

npm install webpack-cli -D

当成功后,我们再次运行 webpack-dev-server 可以看到已经启动了服务器了,端口号默认是 8080, 然后我们访问 http://localhost:8080/index.html  就可以访问到我们项目中页面了。

6.1 实时预览
webpack在启动时可以开启监听模式,默认是关闭的,开启后webpack会监听本地文件系统的变化,在发生变化时候会重新构建出新的结果,在上面运行
webpack-dev-server 后,我们需要打开一个新的命令行,在命令行中输入如下命令来开启监听模式:

webpack --watch

当项目中入口文件或入口依赖的文件有改变的时候,它会自动重新构建,构建完成后会自动刷新下页面,但是如果修改的不是入口文件或依赖的文件
是不会有任何效果的,比如修改的是index.html 是不会重新构建的。但是要完成上面的实时预览,html页面的bundle.js 要直接引入即可:如下html页面代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
  <div id="app"></div>
  <script src="bundle.js"></script>
</body>
</html>

那为什么 http://localhost:8080/bundle.js 这样也能访问的到呢?原因是DevServer会将webpack构建出的文件保存在内存中,DevServer不会理会
webpack.config.js里配置的output.path属性的。

6.2 模块热替换

除了上面介绍的改动本地入口文件或依赖文件后,会自动打包,然后会自动刷新浏览器即可看到更新效果外,我们还可以使用模块热替换技术,

模块热替换技术能做到在不重新加载整个网页的情况下,通过将已更新的模块替换旧模块,它默认是关闭的,要开启模块热替换,我们只需在启动DevServer时带上 --inline 参数即可。如下命令:

webpack-dev-server --inline  或 webpack-dev-server --inline --hot

webpack-dev-server 有如下两种启动模式:

iFrame: 该模式下修改代码后会自动打包,但是浏览器不会自动刷新。
inline: 内联模式,该模式下修改代码,webpack将自动打包并刷新浏览器。

6.3 支持Source Map
在浏览器中运行javascript代码都是编译器输出的代码,但是如果在代码中碰到一个bug的时候,我们不好调式,因此我们需要 Source Map来映射到源代码上,Webpack支持生成 Source Map, 只需在启动时带上 --devtool source-map参数即可;如下命令:

webpack-dev-server --inline --hot --devtool source-map

注意:每次运行 如上命令,感觉非常长,因此我们可以在项目的根目录的package.json文件的scripts配置中添加如下配置:

"scripts": {
  "dev": "webpack-dev-server --devtool source-map --hot --inline"
}

加上如上配置后,我们只需要在命令行中 运行 npm run dev 即可;

其他配置常见的选项:
--quiet 控制台中不输出打包的信息
--compress 开启gzip的压缩
--progress 显示打包的进度

因此在项目中scripts经常会做如下配置:

"scripts": {
  "dev": "webpack-dev-server --progress --colors --devtool source-map --hot --inline",
  "build": "webpack --progress --colors"
}

这样的话,打包的时候会显示打包进度。

回到顶部

1. context

基础目录,绝对路径,用于从配置中解析入口起点和加载器。什么意思呢?比如如下代码配置:
context: path.resolve(__dirname, ''js''), 含义是使用当前目录下的js文件下查找入口文件。比如如下代码的配置也是可以的:

module.exports = {
  context: path.resolve(__dirname, ''js''),
  entry: ''./main.js''
}

含义是从当前项目目录下的js文件查找main.js文件作为入口文件,如果在当前目录没有找到该入口文件,就会报错。
当然我们也可以如下写配置代码也是可以的:如下代码配置:

module.exports = {
  context: path.resolve(__dirname, ''''),
  entry: ''./js/main.js''
};

或者context配置项不要,它也是默认从当前目录下查找的,因此如果使用context的话,建议加上第二个参数,是从当前目录下那个文件内查找的。或者直接不要这个配置项。

回到顶部

2. entry

应用程序的起点入口,从这个起点开始,应用程序启动执行,如果传递一个数组的话,那么数组的每一项都会执行。它的类型可以是String, array, 或 object;

2.1 string(类型为字符串): 如下配置:

module.exports = {
  entry: ''./js/main.js'',
  output: {
    // 将所有依赖的模块合并输出到一个叫bundle.js文件内
    filename: ''bundle.js'',
    // 将输出的文件都放在dist目录下
    path: path.resolve(__dirname, ''./dist'')
  }
};

2.2 类型为数组

module.exports = {
  entry: [''./js/main.js'', ''./js/main2.js''],
  output: {
    // 将所有依赖的模块合并输出到一个叫bundle.js文件内
    filename: ''bundle.js'',
    // 将输出的文件都放在dist目录下
    path: path.resolve(__dirname, ''./dist'')
  }
};

如果类型为数组的话,将会创建多个主入口,并且把数组中的js打包在一起到一个文件里面去。

2.3 类型为对象时

module.exports = {
  entry: {
    ''main'': ''./js/main.js'',
    ''main2'': ''./js/main2.js''
  },
  output: {
    filename: ''[name].js'', // [name] 的值是entry的键值, 会输出多个入口文件
    // 将输出的文件都放在dist目录下
    path: path.resolve(__dirname, ''./dist'')
  }
};
回到顶部

3. Output

output配置是输出最终想要的代码,它是一个object, 里面包含很多配置项。

3.1 filename 和 path的理解
filename: 输出文件的名称,为string类型.
1) 如果只有一个输出文件,可以将名称写死;如:filename: ''bundle.js'';
path: 文件被写入硬盘的位置。必须是string类型的绝对路径,一般通过Node.js的path模块获取绝对路径,如下代码:
path: path.resolve(__dirname, ''./dist'')

单个入口配置代码如下:

{
  entry: ''./js/main.js'',
  output: {
    filename: ''bundle.js'',
    path: path.resolve(__dirname, ''./dist'')
  }
}

多个入口

如果有多个chunk要输出时,就需要借助[name]变量了,webpack会为每个chunk取一个名称,因此我们根据chunk的名称来区分输出的文件名。如下:
filename: ''[name].js''

多个入口配置代码如下:

module.exports = {
  entry: {
    ''main'': ''./js/main.js'',
    ''main2'': ''./js/main2.js''
  },
  output: {
    filename: ''[name].js'', // [name] 的值是entry的键值, 会输出多个入口文件
    // 将输出的文件都放在dist目录下
    path: path.resolve(__dirname, ''./dist'')
  }
};

如上配置,会输出 main.js 和 main2.js。
内置变量除了包括name,还包括,id, hash, chunkhash。

id: Chunk的唯一标识,从0开始。
hash: Chunk的唯一标识的Hash值。比如[hash:8] 代表8位的hash值。默认是20位。
chunkhash: Chunk内容的Hash值。

如下hash配置代码:

entry: {
  ''main'': ''./js/main.js'',
  ''main2'': ''./js/main2.js''
},
output: {
  filename: ''[name]_[hash:8].js'', // [name] 的值是entry的键值, 会输出多个入口文件
  // 将输出的文件都放在dist目录下
  path: path.resolve(__dirname, ''./dist'')
}

就会生成 main_xxxx.js 和 main2_xxxx.js 其中xxxx是hash值的随机八位。

3.2 chunkFilename的理解
chunkFilename 和 filename非常类似,但是chunkFilename是未被列在entry中的,但是又需要被打包出来的文件命名配置,什么场景需要这样的呢?
比如 异步按需加载模块的时候,一般这样的文件没有被列在entry中,比如如下项目在js文件内再新建plugins文件夹,存放比如js插件使用的,目录
结构如下:

### 目录结构如下:
demo1                                       # 工程名
|   |--- dist                               # 打包后生成的目录文件             
|   |--- node_modules                       # 所有的依赖包
|   |--- js                                 # 存放所有js文件
|   | |-- demo1.js  
|   | |-- main.js                           # js入口文件
|   | |-- main2.js                          # js的多个入口文件
|   | |-- plugins                           # plugins文件夹,存放js插件类的
|   | | |--- a.js
|   |
|   |--- webpack.config.js                  # webpack配置文件
|   |--- index.html                         # html文件
|   |--- styles                             # 存放所有的css样式文件                              
|   |--- .gitignore  
|   |--- README.md
|   |--- package.json

如上目录结构 在js文件夹内,再新建plugins文件夹,里面包含一个a.js文件;代码如下:

function a() {
  console.log(''a.js'');
}
module.exports = a;

然后我们在main2.js入口文件如下编写代码;使用异步方式引用a.js; 代码如下:

require.ensure([''./plugins/a.js''], function(require) {
  var aModule = require(''./plugins/a.js'');
}, ''a'');

然后在webpack的output配置添加 chunkFilename 配置如下:

module.exports = {
  context: path.resolve(__dirname, ''''),
  entry: {
    ''main'': ''./js/main.js'',
    ''main2'': ''./js/main2.js''
  },
  output: {
    filename: ''[name]_[hash:8].js'', // [name] 的值是entry的键值, 会输出多个入口文件
    chunkFilename: ''[name].min.js'', 
    // 将输出的文件都放在dist目录下
    path: path.resolve(__dirname, ''./dist'')
  }
};

其中上面的 require.ensure() API的第三个参数是给这个模块命名的,因此在webpack配置完成后,继续打包下,会在dist文件夹下打出 a.min.js 文件
了。所以这就是 chunkFilename 的用途场景了。

3.3 publicPath的理解

output.path 是指所有输出文件的本地文件目录(绝对路径)。比如配置如下:

output: {
  filename: ''bundle.js'',
  // 将输出的文件都放在dist目录下
  path: path.resolve(__dirname, ''dist'')
}

那么webpack会将所有文件输出到 dist/下。也就是说path是存放打包后的文件的输出目录。

正式环境下publicPath的理解:
publicPath正式环境可以理解为改变相对目录下的静态资源文件的路径为正确的路径。比如图片引入的是相对路径,可以配置publicPath成为正确的路径。
它是指定资源文件引用的目录(相对于服务器的根目录来讲)。

先看styles/main.css代码如下:

#app {
  font-size: 18px;
  width: 200px;
  height: 200px;
  backround: url(''../images/1.jpg'') no-repeat;
}

iamges文件夹内有一张图片为1.jpg, 因此上面是css的引入路径。然后手动创建 index.html代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <link href="dist/main.css" rel="stylesheet" type="text/css" />
</head>
<body>
  <div id="app"></div>
  <script src="dist/bundle.js"></script>
</body>
</html>

现在我们执行 npm run build 进行打包后,打开index.html发现css中图片的引用的路径为:backround: url(1.jpg) no-repeat; 很明显图片的引用路径不对,它引入是根目录下的图片,因此如果我们在打包的时候加上 publicPath,配置如下:

output: {
  filename: ''bundle.js'',
  // 将输出的文件都放在dist目录下
  path: path.resolve(__dirname, ''dist''),
  publicPath: ''/dist/''
}

重新打包下,再看下css引入路径为 backround: url(/dist/1.jpg) no-repeat;说明引入是对的。

开发环境下publicPath的理解:

output的配置如下:

output: {
  filename: ''bundle.js'',
  // 将输出的文件都放在dist目录下
  path: path.resolve(__dirname, ''dist''),
  // publicPath: ''/dist/''
}

然后把dist目录删除掉,执行 npm run dev后,开发环境打包后并没有生成dist目录,而我们的index.html引入了 dist/bundle.js 和 dist/main.css, 因此页面会发现找不到js和css文件。那么打包后文件放在那里去了呢?我们可以看如下图:

启动了webpack-dev-server, 然后整个项目运行在localhost:8080下面,也就是服务器地址是localhost:8080, 当我们在浏览器中输入服务器地址,服务器会签就会到服务器请求js 文件,js的地址是dist/bundle.js, 没有,报错了。
看如上截图的:wepback output is served from / , 这里指明了webpack 打包后文件放到了/ 目录下,也就是根目录下,webpack-dev-server 进行打包时
它默认把css和js及图片打包到根目录下。
现在把output配置改成如下:

output: {
  filename: ''bundle.js'',
  // 将输出的文件都放在dist目录下
  path: path.resolve(__dirname, ''dist''),
  publicPath: ''/dist/''
};

再进行运行下 npm run dev 后看到如下所示:

wepback output is served from /dist/ 这里指明了webpack 打包后文件放到了/dist/ 目录下了,因为js和css文件可以重新访问了。

3.4 crossOriginLoading

Webpack输出的部分代码有可能需要异步加载,而异步加载是通过JSON方式实现的。JSONP的原理是动态地向HTML中插入一个<script src="url">
</script>,crossOriginLoading则是用于配置这个异步插入的标签的 crossorigin的值。
script标签的crossorigin属性可以取以下的值:
1. anonymous(默认),启用跨域加载,在加载此脚本资源时不会带上用户的Cookies; 即发送不带凭据的 credential的请求。
2. use-credentials 启用跨域加载,在加载此脚本资源时会带上用户的Cookies. 发送带凭据的credential的请求。
3. false 禁用跨域加载。

3.5 libraryTarget 和 library

这两个属性大家可能比较陌生,一般项目中不需要关注这两个属性,但是当我们开发类库,使用webpack去构建一个可以被其他模块导入使用的库时会使用到。一般情况下,webpack对js模块进行打包,即多个js模块和一个入口模块,打包成一个bundle文件,可以直接被浏览器或者其他javascript引擎执行,

相当于直接编译生成一个完成的可执行文件。但是当我们需要发布一个javascript库的时候,比如在npm社区中发布自己的库,这个时候我们的webpack就需要相应的配置.

libraryTarget 是配置以何种方式导出库。可以是 var, commonjs, ''commonjs2'', amd, this,umd模式等。
library 配置导出库的名称。
他们一般都组合使用的。

我们下面来编写一个简单的库,假如名字叫 demo1.js,代码如下:

function sayHello() {
  console.log(''Hello'');
}

function sayFunc() {
  console.log(''say'');
}

export default {
  sayHello: sayHello,
  sayFunc: sayFunc
}

然后我们在main.js代码引入该文件

import foo from ''./demo1.js'';

console.log(foo);
foo.sayHello(); // 可以执行

webpack打包配置如下: 

entry: ''./js/main.js'',
output: {
  filename: ''bundle.js'',
  // 将输出的文件都放在dist目录下
  path: path.resolve(__dirname, ''dist'')
}

这样会输出一个立即执行的函数,bundle代码大致结构如下:

(function(modules) { // webpackBootstrap
  var installedModules = {};
  function __webpack_require__(moduleId) {
    // ....
  }
  return __webpack_require__(__webpack_require__.s = "./js/main.js");
})
({
  "./js/demo1.js":
  (function(module, __webpack_exports__, __webpack_require__) {
      "use strict";
      eval("__webpack_require__.r(__webpack_exports__);\nfunction sayHello() {\n  console.log(''Hello'');\n}\n\nfunction sayFunc() {\n  console.log(''say'');\n}\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n  sayHello: sayHello,\n  sayFunc: sayFunc\n});\n\n//# sourceURL=webpack:///./js/demo1.js?");
  }),
  "./js/main.js":
  (function(module, __webpack_exports__, __webpack_require__) {
      "use strict";
      eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _demo1_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./demo1.js */ \"./js/demo1.js\");\n\n\nconsole.log(_demo1_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n_demo1_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].sayHello();\n\n\n\n//# sourceURL=webpack:///./js/main.js?");
  })
});

3.5.1 commonjs2 模式
如果我们需要将打包返回值交给编译后的文件 module.export, 因此我们这边可以使用 libraryTarget 和 library, webpack配置如下:

entry: ''./js/main.js'',
output: {
  filename: ''bundle.js'',
  // 将输出的文件都放在dist目录下
  path: path.resolve(__dirname, ''dist''),
  libraryTarget: ''commonjs2'',
  library: ''util''
}

main.js 代码如下:

import demo1 from ''./demo1.js'';

demo1.js 代码如下:

function sayHello() {
  console.log(''Hello'');
}

function sayFunc() {
  console.log(''say'');
}

export default {
  sayHello: sayHello,
  sayFunc: sayFunc
}

打包后的文件是如下格式代码:

module.exports = (function(modules) { // webpackBootstrap
  var installedModules = {};
  function __webpack_require__(moduleId) {
    // ....
  }
  return __webpack_require__(__webpack_require__.s = "./js/main.js");
})
({
  "./js/demo1.js":
  (function(module, __webpack_exports__, __webpack_require__) {
      "use strict";
      eval("__webpack_require__.r(__webpack_exports__);\nfunction sayHello() {\n  console.log(''Hello'');\n}\n\nfunction sayFunc() {\n  console.log(''say'');\n}\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n  sayHello: sayHello,\n  sayFunc: sayFunc\n});\n\n//# sourceURL=webpack:///./js/demo1.js?");
  }),
  "./js/main.js":
  (function(module, __webpack_exports__, __webpack_require__) {
      "use strict";
      eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _demo1_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./demo1.js */ \"./js/demo1.js\");\n\n\nconsole.log(_demo1_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n_demo1_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].sayHello();\n\n\n\n//# sourceURL=webpack:///./js/main.js?");
  })
});

那么从npm社区下载库后,使用库的方法是如下:

const util1 = require(''library-name-in-npm'');
util1.xxx(); // xxx就是 某个方法名称

3.5.2 commonjs
编写的库将通过commonjs导出。
webpack 配置代码如下:

entry: ''./js/main.js'',
output: {
  filename: ''bundle.js'',
  // 将输出的文件都放在dist目录下
  path: path.resolve(__dirname, ''dist''),
  libraryTarget: ''commonjs'',
  library: ''util''
}

打包后的文件变成如下代码:

exports["util"] =
  (function(modules) { // webpackBootstrap
    var installedModules = {};
    function __webpack_require__(moduleId) {
      // ....
    }
    return __webpack_require__(__webpack_require__.s = "./js/main.js");
  })
  ({
    "./js/demo1.js":
   (function(module, __webpack_exports__, __webpack_require__) {
    "use strict";
    eval("__webpack_require__.r(__webpack_exports__);\nfunction sayHello() {\n  console.log(''Hello'');\n}\n\nfunction sayFunc() {\n  console.log(''say'');\n}\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n  sayHello: sayHello,\n  sayFunc: sayFunc\n});\n\n//# sourceURL=webpack://util/./js/demo1.js?");
  }),
    "./js/main.js":
    (function(module, __webpack_exports__, __webpack_require__) {
      "use strict";
      eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _demo1_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./demo1.js */ \"./js/demo1.js\");\n\n\n\n\n\n//# sourceURL=webpack://util/./js/main.js?");

    })
});

如上代码:配置了 output.library = ''LibraryName''; webpack就会输出代码格式为:
exports[''LibraryName''] = lib_code;

使用库的方法代码如下:

require(''library-name-in-npm'')[''LibraryName''].doSomething();

注意:lib_code 为所有的webpack打包的代码;library-name-in-npm 是指模块被发布到npm代码仓库的名称。

3.5.3 this
编写的库将通过this被赋值给library指定的名称。

webpack配置代码如下:

entry: ''./js/main.js'',
output: {
  filename: ''bundle.js'',
  // 将输出的文件都放在dist目录下
  path: path.resolve(__dirname, ''dist''),
  libraryTarget: ''this'',
  library: ''util''
}

打包后的js文件如下格式:

this["util"] =
  (function(modules) { // webpackBootstrap
    var installedModules = {};
    function __webpack_require__(moduleId) {
      // ....
    }
    return __webpack_require__(__webpack_require__.s = "./js/main.js");
  })
  ({
    "./js/demo1.js":
   (function(module, __webpack_exports__, __webpack_require__) {
    "use strict";
    eval("__webpack_require__.r(__webpack_exports__);\nfunction sayHello() {\n  console.log(''Hello'');\n}\n\nfunction sayFunc() {\n  console.log(''say'');\n}\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n  sayHello: sayHello,\n  sayFunc: sayFunc\n});\n\n//# sourceURL=webpack://util/./js/demo1.js?");
  }),
    "./js/main.js":
    (function(module, __webpack_exports__, __webpack_require__) {
      "use strict";
      eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _demo1_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./demo1.js */ \"./js/demo1.js\");\n\n\n\n\n\n//# sourceURL=webpack://util/./js/main.js?");

    })
});

使用库的方法如下:

this.LibraryName.doSomething();

3.5.4 window
编写的库将通过window赋值给library指定的名称,输出的代码格式如下:
window[''LibraryName''] = lib_code;

webpack的配置如下:

entry: ''./js/main.js'',
output: {
  filename: ''bundle.js'',
  // 将输出的文件都放在dist目录下
  path: path.resolve(__dirname, ''dist''),
  libraryTarget: ''window'',
  library: ''util''
}

打包后的js代码如下:

window["util"] =
  (function(modules) { // webpackBootstrap
    var installedModules = {};
    function __webpack_require__(moduleId) {
      // ....
    }
    return __webpack_require__(__webpack_require__.s = "./js/main.js");
  })
  ({
    "./js/demo1.js":
   (function(module, __webpack_exports__, __webpack_require__) {
    "use strict";
    eval("__webpack_require__.r(__webpack_exports__);\nfunction sayHello() {\n  console.log(''Hello'');\n}\n\nfunction sayFunc() {\n  console.log(''say'');\n}\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n  sayHello: sayHello,\n  sayFunc: sayFunc\n});\n\n//# sourceURL=webpack://util/./js/demo1.js?");
  }),
    "./js/main.js":
    (function(module, __webpack_exports__, __webpack_require__) {
      "use strict";
      eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _demo1_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./demo1.js */ \"./js/demo1.js\");\n\n\n\n\n\n//# sourceURL=webpack://util/./js/main.js?");

    })
});

使用库的方法如下代码:

window.LibraryName.doSomething();

3.5.5 global
编写的库将通过global赋值给通过library指定的名称,即把库挂载到global上,输出格式的代码如下:
global[''LibraryName''] = lib_code;

和上面的window是一样的,无非就是把window改成global;

使用库的方法如下所示:

global.LibraryName.doSomething();

也可以打包成 ''amd'' 或 ''umd'' 模式结构代码, 在此介绍省略哦~

回到顶部

4. 模式(mode)

提供mode配置项,告诉webpack使用对应的模式。

在webpack配置中提供mode选项。如下代码:

module.exports = {
  mode: ''production'' // 或开发环境下 ''development''
};

注意:使用 development模式代码不会被压缩,使用 production 代码会被压缩。

也可以在CLI参数中传递,比如如下代码:
webpack --mode=production

回到顶部

5.理解使用Loader

我们都知道webpack是适用于资源进行打包的,里面的所有资源都是模块,内部实现了对模块资源进行加载机制,但是webpack只能处理js模块,如果要处理其他类型的文件,就需要使用loader进行转换。Loader可以理解为是模块和资源的转换器,它本身也是一个函数,接收源文件作为参数,返回转换的结果。

配置loader,需要使用rules模块来读取和解析规则,它是一个数组,数组里面中的每一项描述了如何处理部分文件。
1. 条件匹配: 通过配置test,include,exclude三个配置项来选中loader需要应用规则的文件。
2. 应用规则: 对选中的文件通过use配置项来应用loader,可以只应用一个loader或者按照从右往左的顺序应用一组loader(切记:loader使用顺序是从右往左的),也可以向loader传入参数。
3. 重置顺序: Loader执行的顺序默认是从右到左执行的,但是我们可以通过enforce选项可以将其中一个Loader的执行顺序放到最前或最后。

具体的配置代码可以参考如下:

module.exports = {
  module: {
    rules: [
      {
        // 正则匹配 以 js结尾的
        test: /\.js$/,
        // babel 转换js文件,?cacheDirectory 用于缓存babel的编译结果,加快重新编译的速度
        use: [''babel-loader?cacheDirectory''],
        // include只包含src目录下的js文件,加快查找速度
        include: path.resolve(__dirname, ''src'')
      },
      {
        // 正则匹配以 styl结尾的文件
        test: /\.styl$/,
        /* 
          use使用顺序从右到左执行,先使用stylus-loader插件去解析以styl结尾的文件成css文件,
          再使用css-loader插件去读取css文件,最后由 style-loader 将css的内容注入到javascript里面。
        */
        use: [''style-loader'', ''css-loader'', ''stylus-loader''],

        // 排除node_modules目录下的文件
        exclude: path.resolve(__dirname, ''node_modules'')
      },
      {
        // 对非文本文件采用file-loader去加载
        test: /\.(gif|png|jpe?g|eot|woff|ttf|svg|pdf)$/,
        use: [''file-loader'']
      }
    ]
  }
}

注意:在loader需要传入多个参数时,我们可以通过一个Object来描述,如下面是babel-loader配置:

use: [
  {
    loader: ''babel-loader'',
    options: {
      cacheDirectory: true
    },
    /*
      enforce: ''post'' 的含义是将Loader执行的顺序放到最后
      enforce: ''pre'' 的含义是将Loader执行顺序放到最前面
    */
    enforce: ''post''
  }
]

当然,上面的test,include,exclude配置也可以传入多个,因此他们也支持数组的方式来传递了。比如如下配置:

{
  test: [
    /\.js$/,
    /\.jsx$/
  ],
  include: [
    path.resolve(__dirname, ''src''),
    path.resolve(__dirname, ''src2'')
  ],
  exclude: [
    path.resolve(__dirname, ''node_modules''),
    path.resolve(__dirname, ''node_modules2'')
  ]
}
回到顶部

6.理解noParse

该配置项可以让webpack忽略对部分未采用模块化文件的递归解析和处理,该忽略的文件不能包含import,require, define等模块化语句。
那么这样做的好处是可以提高构建性能,比如像一些库jquery等就没有必要去使用webpack去递归解析和处理了。
使用配置代码如下:

module.exports = {
  module: {
    noParse: /jquery|xxjs/
  }
}

也可以使用函数,但是webpack需要从3.0版本才支持;如下配置代码:

module.exports = {
  module: {
    noParse: (content) => {
      // content代表一个模块的文件路径
      return /jquery|xxjs/.test(content);
    }
  }
}
回到顶部

7. 理解alias

resolve.alias 是通过别名来将原导入路径映射成一个新的导入路径。比如如下配置:

module.exports = {
  entry: ''./js/main.js'',
  output: {
    filename: ''bundle.js'',
    // 将输出的文件都放在dist目录下
    path: path.resolve(__dirname, ''dist'')
  },
  resolve: {
    alias: {
      components: ''./src/components''
    }
  }
}

如上代码配置,当我通过 import xxx from ''components/xxx'' 导入时,实际上被alias替换成了
import xxx from ''./src/components/xxx'';

回到顶部

8.理解extensions

在使用 import 导入文件时,有时候没有带入文件的后缀名,webpack会自动带上后缀去访问文件是否存在,那么默认的后缀名为
[''.js'', ''.json'']; 即:
extensions: [''.js'', ''.json'']; 如果我们想自己配置.vue后缀名,防止在导入文件时候不需要加上后缀;我们可以使用webpack做如下配置:

module.exports = {
  entry: ''./js/main.js'',
  output: {
    filename: ''bundle.js'',
    // 将输出的文件都放在dist目录下
    path: path.resolve(__dirname, ''dist'')
  },
  resolve: {
    alias: {
      components: ''./src/components''
    },
    extensions: [''.js'', ''.vue''];
  }
}
回到顶部

9.理解Externals

Externals 用来告诉webpack在构建代码时使用了不处理应用的某些依赖库,依然可以在代码中通过AMD,CMD或window全局方式访问。
什么意思呢?就是说我们在html页面中引入了jquery源文件后,比如如下代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <script src="http://code.jquery.com/jquery-1.12.0.min.js"></script>
  <link href="dist/main.css" rel="stylesheet" type="text/css" />
</head>
<body>
  <div id="app"></div>
  <script src="dist/bundle.js"></script>
</body>
</html>

但是我们想在模块化的源代码里导入和使用jquery,首先我们肯定需要安装下 jquery依赖包,npm install --save jquery, 然后我们编写如下代码进行使用:

const $ = require(''jquery'');
console.log($);

构建打包后我们会发现输出的文件里面包含jquery的内容,这导致了jquery库引入了两次,并且导致了bundle.js文件变得更大,浪费加载流量。因此 Externals 配置项就是来解决这个问题的。

通过externals 可以告诉webpack在javascript运行环境中已经内置了哪些全局变量,不用将这些代码打包到代码里面去。
因此我们可以做如下配置:

module.export = {
  externals: {
    jquery: ''jQuery''
  }
};

02-webpack的基本配置和输入webpack实现自动打包

02-webpack的基本配置和输入webpack实现自动打包

1安装webPack的方式
    01==》    第一次全局安装  npm i webpack -g  第一次安装了之后以后就不需要在安装了
查看webpack的版本,webpack -V 我的版本是3.8.1
如果出现对应的版本, 你就不需要再次执行
npm i webpack -g
说明你已经安装过webpack了;
       02==》 创建一个文件夹;如testwebpack
        在项目根录下(testwebpack)运行 npm i webpack --save-dev 安装到项目依赖中去 

会出现两个文件夹;node_modules package.json这个两个文件夹
        如果没有 package.json ;你就执行   npm init -y 

 

2尝试使用webpack

         安装包描述文件  npm init -y  新版本的node会自带这个的;
npm i jquery
-S 安装jq 保存到依赖列表中去了;
此时你就可以在package.json 看见自己已经安装了jquery了

           testwebpack目录下==》新建src目录 在src目录下 新建index.html文件 在src目录下新建main.js文件
         src目录下创建 imgs文件夹 和js文件夹(文件结构不要错了)

       

         在main.js文件中导入jq   导入的语法是  import **  from    **它是es6中导入模块的方式 
            1 如 import $ from  'jquery'   注意大小写
             从引入文件可以知道 首先是在自己的兄弟目录中去找  
然后去父级目录的兄弟目录中去找 然后依次类推(重点)
               import $ from "jquery";
             $(function(){
                console.log("haha")
             })
             在node.js中 你要是这样写的 const $=require("Jquery")
         

             由于es6的import导包的方式台高级了 所以浏览器解析不了 所以import $ from 'Jquery'汇报错
             所以需要webpack来惊醒转化
运行webpack。
webpack ./src/mian.js  ./dist/testindex.js 在dist中被编译的文件是为testindex.js

此时你就会发现,项目目录下多了一个dist文件夹;和文件夹下有个文件;

注意:如果如果你配置了webpack.config.js,再次运行上面的命令;会报错

  

配置webpack和命令运行;

  3在项目的跟目录下创建webpack.config.js文件配置如下;

    const path = require("path");
   module.exports={
        entry:path.join(__dirname,'./src/main.js'),//入口文件 使用webpack要打包哪一个文件
            output:{ 输出相关的配置
                path:path.join(__dirname,'./dist'),1)">指定打包好的文件会输出到哪一个目录(dist)下去
                filename:"testindex.js" //指定打包好的文件的名称叫什么名字
             }
   }


  3所以在index中的时候我们就引入被webpack编译好的js文件就可以了
  <script src="../dist/testindex.js"></script>
这里引入的时候需要注意的点是:
之所以是testindex.js是因为配置写的编译成testindex.js

    如果你已经向上面这样配置了  可以直接在项目的根目录下webpack就可以运行了 

    因为已经配置好了

 

webpack 能够处理的问题
ebpack能够处理js文件之间的互相依赖关系
webpack能够处理js的兼容性问题   能装将es6的语法转化为es5的语法  

 

我们可以发现引入jquery的两种方式

const $=require("Jquery")

import $ from  'jquery'

 

2020年你不能不知道的webpack基本配置

2020年你不能不知道的webpack基本配置

前言

在很久很久以前,在我们前端还只是页面切图仔的年代,我们开发一个html页面,通常会遇到这些情况:

  • 需要引入十几个css和js文件,而且因为他们彼此间有着依赖关系,所以引入的顺序还不能乱。
  • 传统的html+css+js开发方式不能不能很好地运用less/scss等css预处理器以及ES6+的高级语法。
  • 代码复用性差,可维护性差。

此时就需要一个处理这些问题的工具,webpack应运而生。

webpack可以看做是模块打包工具:它将各种静态资源(比如:javaScript 文件,图片文件,css文件等)视为模块,它能够对这些模块进行解析优化和转换等操作,最后将它们打包在一起,打包后的文件可用于在浏览器中使用。

相关推荐

本人github: github.com/Michael-lzg
我的掘金:https://juejin.im/user/5b52fd...
从零开始构建一个webpack项目
总结几个webpack打包优化的方法

webpack的优点:

  • 代码转换: typeScript 编译成 javaScriptscss,less 编译成 css.
  • 文件优化:压缩 javaScriptcsshtml 代码,压缩合并图片。
  • 代码分割:提取多个页面的公共代码、提取首屏不需要执行部分的代码让其异步加载。
  • 模块合并:在采用模块化的项目里会有很多个模块和文件,需要构建功能把模块分类合并成一个文件。
  • 自动刷新:监听本地源代码的变化,自动重新构建、刷新浏览器。
  • 扩展性强,插件机制完善。

webpack打包过程:

1.利用babel完成代码转换,并生成单个文件的依赖
2.从入口开始递归分析,并生成依赖图谱
3.将各个引用模块打包为一个立即执行函数
4.将最终的bundle文件写入bundle.js中

Webpack 的四大核心:

  • entry:js 入口源文件
  • output:生成文件
  • loader:进行文件处理
  • plugins:插件,比 loader 更强大,能使用更多 webpack 的 api

Entry

webpack 应该使用哪个模块做为入口文件,来作为构建其内部依赖图的开始。进去入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的,每个依赖项随即被处理,最后输出到称之为 bundles 的文件中。

单⼊⼝:entry 是⼀个字符串

module.exports = {
  entry: ''./src/index.js''
}

多⼊⼝:entry 是⼀个对象

module.exports = {
  entry: {
    index: ''./src/index.js'',
    manager: ''./src/manager.js''
  }
}

Output

告诉 webpack 在哪里输出它所创建的 bundles,以及如何命名这些文件,这些都可以在webpack的配置文件中指定。

单⼊⼝配置

module.exports = {
    entry: ''./src/index.js'',
    output: {
        filename: ''bundle.js’,
        path: __dirname + ''/dist''
    }
};

多⼊⼝配置

module.exports = {
  entry: {
    app: ''./src/app.js'',
    search: ''./src/search.js''
  },
  output: {
    filename: ''[name].js'',
    path: __dirname + ''/dist''
  }
}

通过[name]占位符确保⽂件名称的唯⼀

Loader

loaderwebpack 能够去处理那些非 javaScript 文件(webpack 自身只理解 javaScript)。loader 可以将所有类型的文件转换为 webpack 能够处理的有效模块,然后你就可以利用 webpack 的打包能力,对它们进行处理。

loader的特点

  • 一个Loader 的职责是单一的,只需要完成一种转换
  • 一个Loader 其实就是一个Node.js 模块,这个模块需要导出一个函数
  • loader 总是从右到左地被调用。

常用的loader

处理样式

  • css-loader: 加载.css 文件,
  • style-loader:使用 style 标签将 css-loader 内部样式注入到我们的 html 页面
  • less-loader, sass-loader: 解析css预处理器

处理 js

  • 让你能使用最新的js代码(ES6,ES7...)
  • 让你能使用基于js进行了拓展的语言,比如React的JSX;

处理文件

处理图片资源时,我们常用的两种loader是file-loader或者url-loader,两者的主要差异在于。url-loader可以设置图片大小限制,当图片超过限制时,其表现行为等同于file-loader,而当图片不超过限制时,则会将图片以base64的形式打包进css文件,以减少请求次数

处理.vue文件

vue-loaderwebpack 的加载器模块,它使我们可以用 .vue 文件格式编写单文件组件。单文件组件文件有三个部分,即模板、脚本和样式。 vue-loader 模块允许 webpack 使用单独的加载器模块(例如 sass 或 scss 加载器)提取和处理每个部分。该设置使我们可以使用 .vue 文件无缝编写程序。

开发一个loader

需求:手写一个 loader,将 ''kobe'' 转换成 ''Black Mamba''。当然大家可以根据自己的需求进行设计。这里只是讲解方法。

1、编写 loader

在根目录下,新建目录 kobe-loader 作为我们编写 loader 的名称,执行 npm init -y 命令,新建一个模块化项目,然后新建 index.js 文件,相关源码如下:

module.exports = function(content) {
  return content && content.replace(/kobe/gi, ''Black Mamba'')
}

2、注册模块

正常我们安装的 loader 是从 npm 下载安装,但是我们可以在 kobe-loader 目录底下使用 npm link 做到在不发布模块的情况下,将本地的一个正在开发的模块的源码链接到项目的 node_modules 目录下,让项目可以直接使用本地的 npm 模块。

npm link

然后在项目根目录执行以下命令,将注册到全局的本地 npm 模块链接到项目的 node_modules

$ npm link kobe-loader

注册成功后,我们可以在 node_modules 目录下能查找到对应的 loader

3、在 webpack 中配置 loader

webpack.base.conf.js 加上如下配置

{
  test:/\.js/,
  loader: ''kobe-loader''
}

此时,我们在所有 js 文件下书写的 ''kobe'' 就全部替换成 ''Black Mamba''了。

4、配置参数

上面我们是写死的替换文案,假如我想通过配置项来改变,可以在 loader 中做以下调整

// custom-loader/index.js
var utils = require(''loader-utils'')
module.exports = function (content) {
  const options = utils.getOptions(this)
  return content && content.replace(/kobe/gi, options.name)
}

// webpack.base.conf.js
{
  test:/\.js/,
  use: {
    loader: ''kobe-loader'',
    options: {
      name: ''kobe'',
    }
  }
}

Plugin

专注处理 webpack 在编译过程中的某个特定的任务的功能模块,可以称为插件。

Plugin 的特点

  • 是一个独立的模块
  • 模块对外暴露一个 js 函数
  • 函数的原型 (prototype) 上定义了一个注入 compiler 对象的 apply方法 apply 函数中需要有通过 compiler 对象挂载的 webpack 事件钩子,钩子的回调中能拿到当前编译的 compilation 对象,如果是异步编译插件的话可以拿到回调 callback
  • 完成自定义子编译流程并处理 complition 对象的内部数据
  • 如果异步编译插件的话,数据处理完成后执行 callback 回调。

常用Plugin

  • HotModuleReplacementPlugin 代码热替换。因为 Hot-Module-Replacement 的热更新是依赖于 webpack-dev-server,后者是在打包文件改变时更新打包文件或者 reload 刷新整个页面,HRM 是只更新修改的部分。
  • HtmlWebpackPlugin, 生成 html 文件。将 webpack 中entry配置的相关入口 chunk 和 extract-text-webpack-plugin抽取的 css 样式 插入到该插件提供的template或者templateContent配置项指定的内容基础上生成一个 html 文件,具体插入方式是将样式link插入到head元素中,script插入到head或者body中。
  • ExtractTextPlugin, 将 css 成生文件,而非内联 。该插件的主要是为了抽离 css 样式,防止将样式打包在 js 中引起页面样式加载错乱的现象。
  • NoErrorsPlugin报错但不退出 webpack 进程
  • UglifyJsPlugin,代码丑化,开发过程中不建议打开。 uglifyJsPlugin 用来对 js 文件进行压缩,从而减小 js 文件的大小,加速 load 速度。uglifyJsPlugin 会拖慢 webpack 的编译速度,所有建议在开发简单将其关闭,部署的时候再将其打开。多个 html 共用一个 js 文件(chunk),可用 CommonsChunkPlugin
  • purifycss-webpack  。打包编译时,可剔除页面和 js 中未被使用的 css,这样使用第三方的类库时,只加载被使用的类,大大减小 css 体积
  • optimize-css-assets-webpack-plugin   压缩 css,优化 css 结构,利于网页加载和渲染
  • webpack-parallel-uglify-plugin   可以并行运行 UglifyJS 插件,这可以有效减少构建时间

开发一个 plugin

  • Webpack 在编译过程中,会广播很多事件,例如 run、compile、done、fail 等等,可以查看官网;
  • Webpack 的事件流机制应用了观察者模式,我们编写的插件可以监听 Webpack 事件来触发对应的处理逻辑;
  • 插件中可以使用很多 Webpack 提供的 API,例如读取输出资源、代码块、模块及依赖等;

1、编写插件

在根目录下,新建目录 my-plugin 作为我们编写插件的名称,执行 npm init -y 命令,新建一个模块化项目,然后新建 index.js 文件,相关源码如下:

class MyPlugin {
  constructor(doneCallback, failCallback) {
    // 保存在创建插件实例时传入的回调函数
    this.doneCallback = doneCallback
    this.failCallback = failCallback
  }
  apply(compiler) {
    // 成功完成一次完整的编译和输出流程时,会触发 done 事件
    compiler.plugin(''done'', stats => {
      this.doneCallback(stats)
    })
    // 在编译和输出的流程中遇到异常时,会触发 failed 事件
    compiler.plugin(''failed'', err => {
      this.failCallback(err)
    })
  }
}
module.exports = MyPlugin

2、注册模块

按照以上的方法,我们在 my-plugin 目录底下使用 npm link 做到在不发布模块的情况下,将本地的一个正在开发的模块的源码链接到项目的 node_modules 目录下,让项目可以直接使用本地的 npm 模块。

npm link

然后在项目根目录执行以下命令,将注册到全局的本地 npm 模块链接到项目的 node_modules 下

$ npm link my-plugin

注册成功后,我们可以在 node_modules 目录下能查找到对应的插件了。

3、配置插件

在 webpack.base.conf.js 加上如下配置

plugins: [
  new MyPlugin(
    stats => {
      console.info(''编译成功!'')
    },
    err => {
      console.error(''编译失败!'')
    }
  )
]

执行运行 or 编译命令,就能看到我们的 plugin 起作用了。

推荐文章

从零开始构建一个webpack项目
总结几个webpack打包优化的方法
总结移动端H5开发常用技巧
总结前端性能优化的方法
搭建一个vue-cli的移动端H5开发模板
封装一个toast和dialog组件并发布到npm
一文读尽前端路由、后端路由、单页面应用、多页面应用
浅谈JavaScript的防抖与节流

关注的我的公众号不定期分享前端知识,与您一起进步!

webpack 4.x 解决 webpack-dev-server工具在webpack构建的项目中使用问题

webpack 4.x 解决 webpack-dev-server工具在webpack构建的项目中使用问题

webpack-dev-server工具能实现自动打包编译和热更新

首先将webpack-dev-server安装到项目中

npm install webpack-dev-server -D

这时在命令行窗口中敲 webpack-dev-server 会发现

''webpack-dev-server'' 不是内部或外部命令,也不是可运行的程序
或批处理文件。

这是由于该工具只是安装到本地项目中了

纳尼? 难道要全局安装一下吗???

没必要!!!这时只需在根目录的package.json"scripts"下中添加

"dev": "webpack-dev-server"

 

当然此处可以带一些参数配置:  --open      启动时打开浏览器

              --port      设置端口号

              --contentBase  设置根目录(即 设置 http://localhost:8080 打开时显示哪个界面)

              --hot      热更新

"dev": "webpack-dev-server --open --port 8080 --contentBase src --hot"

 

 

即可使用 npm run dev 来运行项目了

但是笔者在运行项目时 报了以下错误:

该问题的出现是由于webpack没有安装到项目中导致的;只需要将之安装到项目中即可:

npm install webpack -D

但是 运行依然出错:

此问题的出现 通过查阅得知 应该是 webpack 与 webpack-cli版本不一致导致的

于是:

npm uninstall webpack -D
npm install webpack webpack-cli -D 

然后 npm run dev 运行成功  然后就可以http://localhost:8080访问了

如果没有安装成功可能出现的情况是缓存没有清

npm cache clean --force

webpack devServer 学习笔记(深入浅出webpack目录2.6)

webpack devServer 学习笔记(深入浅出webpack目录2.6)

devServer.hot

1、DevServer默认行为是代码更新后自动刷洗整个页面来做实时。
2、hot: true:启用 webpack 的模块热替换特性,不刷新整个页面下通过用新模块替换老模块来做实时预览。
3、完全启用HMR需要使用HotModuleReplacementPlugin。但如果webpack或webpack-dev-server以hot选项启动,这插件会自动添加,不再需要把它添加到webpack.config.js中。

devServer.hotOnly

1、与hot的区别在于,hotOnly作为构建失败时的回退。
2、在某些模块不支持热更新的情况下,前者会自动刷新页面,后者不刷新页面,而在控制台输出热更新失败(这个说法在网上看到的,没操作过)
-- 通过cli使用:webpack-dev-server --hot-only

devServer.inline

1、DevServer的实时预览功能依赖一个注入页面里的代理客户端,接收来自DevServer的命令并负责刷新网页的工作。
2、默认是启动内联模式(inline mode),将处理重载的脚本(代理客户端)插入到bundle中,并且构建信息会出现在浏览器控制台。
3、iframe模式,使用inline:false开启。DevServer将无法直接控制要开发的网页。这时它会通过 iframe 的方式去运行要开发的网页、
4、推荐使用模块热替换的内联模式,因为它包含来自 websocket 的 HMR 触发器

devServer.historyApiFallback

1、用于方便地开发使用了 HTML5 History API 的单页应用。这种单页应用要求服务器在针对任何命中的路由时,都返回一个对应的HTML文件。
2、简单配置,任何404响应都可能需要被替换为index.html

historyApiFallback: true
// 任何请求都会返回index.html文件,适用于只有一个html文件的应用

3、传入一个对象,如多个单页应用组成的应用。需要更加不同的请求返回不同的HTML文件

historyApiFallback: {
   // 使用正则匹配命中路由
  rewrites: [
   // /user 开头的都返回 user.html 
   { from : /^\/user/, to:''/user.html''}, 
   { from : /^\/game/, to:''/game.html''}, 
   // 其他的都返回 index .html 
   { from: /./, to:''/index.html''},
  ]
}

devServer.contentBase

1、配置 DevServer HTTP 服务器的文件根目录,告诉服务器从哪里提供内容。只有在你想要提供静态文件时才需要。devServer.publicPath将用于确定应该从哪里提供 bundle,并且此选项优先。
2、默认情况下,将使用当前工作目录作为提供内容的目录,但是你可以修改为其他目录:

contentBase: path.join(__dirname, "public")

从多个目录提供内容

contentBase: [path.join(__dirname, "public"), path.join(__dirname, "assets")]

禁用contentBase,关闭暴露本地文件:

contentBase: false

3、DevServer 服务器通过 HTTP 服务暴露文件 的方式可分为两类:
.暴露本地文件
.暴露 Webpack构建出的结果,由于构建出的结果交给了 DevServer,所以我们在使用DevServer时,会在本地找不到构建出的文件。
4、只能用来配置暴露本地文件的规则
补充:不知道咋测试这功能--

devServer.headers

在所有响应中添加首部内容,即可以在 HTTP 响应中注入一些 HTTP 响应

headers: {
  "X-Custom-Foo": "bar"
}

devServer.host

指定使用一个 host。默认是 localhost。如果你希望服务器外部可访问,指定如下:host: "0.0.0.0"
命令行:webpack-dev-server --host 0.0.0.0

devServer.port

指定要监听请求的端口号:port: 8080

devServer.allowedHosts

配置一个白名单列表,只有 HTTP 请求的 HOST 在列表里
才正常返回,使用如下:

allowedHosts: [
  //匹配单个域名
  ''host.com'',
  ''subdomain.host.com'',
  ''subdomain2.host.com'',
  // host2.com 和所有的子域名*.host2.com 都将匹配 
  ''host2.com''
]

devServer.disableHostCheck

配置项用于配置是否关闭用于DNS重新绑定的HTTP请求的HOST检查。

disableHostCheck: true
webpack-dev-server --disable-host-check

devServer.https

默认情况下,dev-server通过HTTP提供服务。也可以选择带有HTTPS的HTTP/2提供服务:https: true
DevServer 会自动为我们生成一份 HTTPS 证书。
想用自己的证书, 则可以这样配置:

https: {
  key: fs.readFileSync("/path/to/server.key"),
  cert: fs.readFileSync("/path/to/server.crt"),
  ca: fs.readFileSync("/path/to/ca.pem"),
}

webpack-dev-server --https
webpack-dev-server --https --key /path/to/server.key --cert /path/to/server.crt --cacert /path/to/ca.pem

devServer.clientLogLevel

配置客户端的日志等级,none、 error、 warning、 info。默认为 info 级别,即输出所有类型的日志,设置成 none 时可以不输出任何日志。
clientLogLevel: "none"
webpack-dev-server --client-log-level none

devServer.contentBase

一切服务都启用gzip压缩:compress: true
webpack-dev-server --compress

devServer.open

用于在 DevServer 启动且第一次构建完时,自动用我们的系统的默认浏览器去打开要开发的网页
open: true
webpack-dev-server --open
webpack-dev-server --open ''Google Chrome''

今天关于深入浅出的webpack构建工具---webpack基本配置(一)webpack构建流程步骤的介绍到此结束,谢谢您的阅读,有关02-webpack的基本配置和输入webpack实现自动打包、2020年你不能不知道的webpack基本配置、webpack 4.x 解决 webpack-dev-server工具在webpack构建的项目中使用问题、webpack devServer 学习笔记(深入浅出webpack目录2.6)等更多相关知识的信息可以在本站进行查询。

本文标签: