#1 webpack基础概念

Webpack V4.12.0

1.主要概念

  • 入口 entry
  • 出口 output
  • 加载器 loader
  • 插件 plugins
  • 模式 mode

2.入口 entry

几种用法:

# 1.单个入口 (简写) 语法
# 用法: entry: string | Array<string>
# 如果传入的是字符串数组(即 Array<string> ),将插件多个主入口
# 当你想要将多个依赖文件一起注入,且将他们的依赖稻香到一个 chunk 时
# 传入数组的方式十分有用
const config = {
  entry: './path/to/my/entry/file.js',
};

// entry 属性的单个入口语法
const config = {
  entry: {
    main: './path/to/my/entry/file.js',
  },
};

# 2.对象语法
# 用法:entry: {[entryChunkName: string]: string|Array<string>}
# 这样允许使用 'CommonsChunkPlugin' 从app bunlde 中提取vendor应用到 vendor bundle中
# 并将引用vendor的部分替换为 '__webpack_require__()'调用
# 注意:这个场景webpack官方正在考虑使用分离能力更强的DllPlugin来替换这种场景的使用
const config = {
  entry: {
    app: './src/app.js',
    vendors: './src/vendors.js',
  },
};

# 3.多页面应用程序
# 告诉webpack需要3个独立分离的依赖图
# 分离的依赖图之间是相互独立的,每个bundle中都有一个webpack引导
# 每当页面跳转时,服务器将获取一个新的HTML文档。
# 页面重新加载新的文档,资源也重新下载
# 但是我们可以使用 CommonsChunkPlugin 为每个页面见的应用程序共享代码创建bundle
const config = {
  entry: {
    pageOne: './src/pageOne/index.js',
    pageTwo: './src/pageTwo/index.js',
    pageThree: './src/pageThree/index.js',
  },
};


modules.export = config;

3.输出 output

控制webpack如何向硬盘写入编译的文件

# 将其设置为一个对象
# 'filename': 输出文件的文件名
# 'path': 目标输出目录的绝对路径

# 配置一个单独的bundle.js 输出到 '/home/proj/public/assets'目录下
const config = {
  output: {
    filename: 'bundle.js',
    path: '/home/proj/public/assets',
  },
};


# 多个入口起点
# 使用多个入口起点或者使用像 CommonsChunkPlugin插件插件创建多个单独的 chunk
# 则应该使用 占位符(substitutions) 来确保每个文件具有唯一的名称
const config = {
  // 多个入口
  entry: {
    app: './src/app.js',
    search: './src/search.js',
  },
  // 写入到硬盘 ./dist/app.js 和 ./dist/search.js
  output: {
    filename: '[name].js',
    output: __dirname + '/dist',
  },
};

# 高级用法
# 使用CDN 和 hash的复杂示例
output: {
  path: '/home/proj/cdn/assets/[hash]',
  // 编译时不知道最终输出文件的 publicPath 情况下,publicPath 可以留空
  // 在运行时(at runtime)将在入口文件动态的设置  
  publicPath: 'http://cdn.example.com/assets/[hash]/',
},
  
// 如果编译时不知道 publicPath,可以忽略这个字段,并在入口处设置 '__webpack_public_path__'
__webpack_public_path__ = myRuntimePublicPath

// 剩余的应用程序入口

4.模式 mode

告诉webpack使用相应的 process.env.NODE_ENV 值对打包文件进行优化。

2种模式:

  • development: 启用 NamedChunksPluginNamedModulesPlugin
  • Production: 启用 FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlug, OccurrenceOrderPlugin, SideEffectsFlagPluginUglifyJsPlugin
// webpack.development.config.js
module.exports = {
+ mode: 'development'
- plugins: [
-   new webpack.NamedModulesPlugin(),
-   new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("development") }),
- ]
}


// webpack.production.config.js
module.exports = {
+  mode: 'production',
-  plugins: [
-    new UglifyJsPlugin(/* ... */),
-    new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") }),
-    new webpack.optimize.ModuleConcatenationPlugin(),
-    new webpack.NoEmitOnErrorsPlugin()
-  ]
}

5.加载器 loader

import 或者 加载模块时对模块的源代码进行转换。类似gulp中的task. 加载器可以将不同的语言,比如typescript,转换为js,或者内联图像转换为data URL;又或者运行在js模块中直接 import css文件

简单示例:

// 将ts文件转换为js文件
// 在js模块中引入css文件
# 1.先下载需要的loaders
yarn add -D ts-loader css-loader

# 2.在配置文件中使用loader
const config = {
  //...
  module: {
    rules: [
      { test: /\.tsx?$/, use: 'ts-loader' },
      { test: /\.css$/, use: 'css-loader' },
    ],
  },
};

loader的3种使用方式

  1. 配置文件(webpack.config.js)中使用,在 module.rules中指定

    module: {
      rules: [
        {
          test: /\.css$/,
          // loader 将从数组从右向左执行
          // 即 css-loader先执行,后执行style-loader
          use: [
            { loader: 'style-loader' },
            {
              loader: 'css-loader',
              options: {
                modules: true,
              },
            },
          ],
        },
      ],
    },
    
  2. 内联的方式,在每个 import 语句中显示的指定loader

    # 使用 '!' 将多个loader分开
    # 选项可以穿的查询参数,比如 '?key=value&foo=bar'
    # 或者一个JSON对象,例如 '?{"key": "value", "foo": "bar"}'
    import Styles from 'style-loader!css-loader?modules!./styles.css';
    
    # 推荐使用第一种方式,即配置文件的形式
    
  3. 命令行的形式

    # 对 '.jade' 文件使用 'jade-loader'
    # 对 '.css' 文件使用 'style-loader' 和 'css-loader'
    > webpack --module-bind jade-loader --module-bind 'css=style-loader!css-loader'
    

loader的特点:

  • 支持链式传递
  • 可以使同步的,也可以异步
  • loader运行在Node.js中
  • loader能够使用 options 对象进行配置
  • 插件plugins可以喂loader带来更多的特性
  • loader可以产生额外的任意文件

各种loaders查看

6.插件 plugins

插件的目的是解决loaders无法实现的其他事

插件是一个具有 apply 属性的js对象, apply 属性会被 webpack compiler调用,并且compiler对象可在整个编译生命周期访问

const pluginName = 'ConsoleLogOnBuildWebpackPlugin';

class ConsoleLogOnBuildWebpackPlugin {
  apply(compiler) {
    // tap方法的第一个参数应该用用驼峰式命名的插件名称,建议使用一个常量
    compiler.hooks.run.tap(pluginName, compilation => {
      console.log('webpack 构建过程开始');
    })
  }
}

用法,插件可以携带 参数/选项(arguments/options),在webpack配置中使用插件需要实例化插件:

const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack'); // 使用内置的插件
const path = require('path');

const config = {
  entry: './path/to/my/entry/file.js',
  output: {
    filename: 'my-webpack.bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        use: 'babel-loader',
      },
    ],
  },
  plugins: [
    new webpack.optimize.UglifyJsPlugin(),
    new HtmlWebpackPlugin({ template: './src/index.html' }),
  ],
};

wepack 插件查看

7.模块 modules

在模块化编程中,开发者将程序分解成你上功能块(discrete chunks of functionality),这称之为模块。

webpack支持的模块:

  • ES2015 import 语句
  • CommonJS require() 语句
  • AMD definerequire 语句
  • css/sass/less文件中的 @import 语句
  • 样式(url(...)) 或者 HTML文件(<img src=...>)中的图片链接

webpack通过加载器可以支持各种语言和预编译器编写模块。加载器描述了如何处理非js文件模块,并且在bundle 中引入这些依赖

8.构建目标 targets

因为服务器和浏览器都可以使用JS编写,所以webpack提供了多种构建目标,可以使用 target 属性设置

// 编译为类Node.js环境,使用Node.js的require
module.exports = {
  target: 'node',
};


// 多个Target
// webpack不支持向 target 传入多个字符串
// 但是可以打包2份分离的配置来参加同构的库
let path = require('path');
let serverConfig = {
  target: 'node',
  output: {
    filename: 'lib.node.js',
    path: path.resolve(__dirname, 'dist'),
  },
};

let clientConfig = {
  target: 'web', // 默认是 'web', 可省略这个字段
  output: {
        filename: 'lib.js',
    path: path.resolve(__dirname, 'dist'),
  },
};
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,193评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,306评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,130评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,110评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,118评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,085评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,007评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,844评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,283评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,508评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,395评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,985评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,630评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,797评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,653评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,553评论 2 352