#1 webpack基础概念

作者: JamesSawyer | 来源:发表于2018-06-17 22:40 被阅读11次

    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'),
      },
    };
    

    相关文章

      网友评论

        本文标题:#1 webpack基础概念

        本文链接:https://www.haomeiwen.com/subject/jargeftx.html