我爱编程javascript高级

#1 webpack基础概念

2018-06-17  本文已影响11人  JamesSawyer

Webpack V4.12.0

1.主要概念

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种模式:

// 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的特点:

各种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支持的模块:

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'),
  },
};
上一篇下一篇

猜你喜欢

热点阅读