zoukankan      html  css  js  c++  java
  • webpack使用入门及常用配置总结

    转自:https://www.cnblogs.com/y896926473/articles/6011711.html

    官网:https://www.webpackjs.com/concepts/

    1. webpack简介

    webpack 是一个模块打包工具。它使得模块相互依赖并且可构建等价于这些模块的静态资源。相比于已经存在的模块打包器(module bundler),webpack的开发动机是实现代码分包(Code Splitting )和通过模块化完成代码的无缝集成。webpack可以根据项目需求合并代码,并且支持按需加载。

    webpack的实现目标是:

    • 拆分依赖树(dependency tree)为多个按需加载的chunk
    • 保证快速首屏加载
    • 每种静态资源都可成为模块
    • 能够将第三方库视作一个模块来处理
    • 能够定制模块打包器的几乎任何部分
    • 适合大型项目

    2. webpack基本使用

    安装webpack之前,请确认node已经安装完毕,且npm包管理器可用。

    2.1 全局安装webpack

    npm  install  webpack -g

    2.2 全局安装 webpack-dev-server

    webpack-dev-server是一个轻量级的服务器,使用内存来存储webpack开发环境下的打包文件,并且可以使用模块热更新,修改文件源码后,自动刷新页面将修改同步到页面上,比传统的http服务对开发更加有效。

    npm install webpack-dev-server -g

    2.3 项目搭建

    在项目的根目录下运行:

    npm install webpack --save-dev

    在项目根目录下新建webpack.config.js。我们通过这个文件来处理控制webpack,给出我们想要的输出。

    webpack.config.js的简单的配置如下:

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

    2.4 开发调试

    项目根目录运行:

    webpack-dev-server --progress --colors

    此时,访问: http://localhost:8080/index.bundle.js 即可访问到编译之后的js了。

    2.5 产品发布

    通过webpack打包发布,运行:

    webpack -p

    按照我们上面的webpack.config.js文件的配置,打包成功之后会生成一个build文件夹,里面会包含打包好的js文件,集成了所有的依赖库和业务逻辑代码,我们只需将此build文件夹发布到线上即可。

    3. 常用配置

    3.1 设置入口

    配置那些js需要处理,entry有三种写法,每个入口称为一个chunk。

    • 字符串:
      entry: "./index/index.js" :配置模块会被解析为模块,并在启动时加载。chunk名为默认为main, 具体打包文件名视output配置而定。 
    • 数组
      entry: ['./src/mod1.js', [...,] './src/index.js'] :所有的模块会在启动时 按照配置顺序 加载,合并到最后一个模块会被导出。chunk名默认为main

    • 对象
      entry: {index: '...', login : [...] }:如果传入Object,则会生成多个入口打包文件, key是chunk名,value可以是字符串,也可是数组。

    例如

    entry: {
        index: './index/index.js',
        login: ['./mod/mod1.js', './index/login.js']
    }

    3.2 配置输出目录

    设置入口配置的文件的输出规则,通过output对象实现,常用设置:

    output: {
        path: __dirname + '/build',
        filename: '[name]-[id].js',
        publicPath: '/asstes/'
    }

    其中:

    • output.path :指定输出文件路径,通常设置为__dirname + ‘/build’,
    • output.filename: 输出文件名称,有下面列出的四种可选的变量。 filename项的配置可以是这几种的任意一种或多种的组合。 如 output.filename = ‘[name]-[id].js’, 则输出就是 index-1.js、 login-2.js。
      • [id], chunk的id
      • [name] ,chunk名
      • [hash], 编译哈希值
      • [chunkhash] , chunk的hash值
    • output.publicPath:设置为想要的资源访问路径。访问时,则需要通过类似http://localhost:8080/asstes/index-1.js来访问资源,如果没有设置,则默认从站点根目录加载。

    3.3 设置loader

    loader用于加载某些资源文件。因为webpack本身只能打包common.js规范的js文件,对于其他资源如css,img等,是没有办法加载的,这时就需要对应的loader将资源转化,从而进行加载。

    安装loader

    npm install xxx-loader --save -dev

    其中,XXX为webpack支持的loader名,常用loader:

    a.模板:

        (1)html-loader:将HTML文件导出编译为字符串,可供js识别的其中一个模块

        (2)pug-loader : 加载pug模板

        (3)jade-loader : 加载jade模板(是pug的前身,由于商标问题改名为pug)

        (4)ejs-loader : 加载ejs模板

        (5)handlebars-loader : 将Handlebars模板转移为HTML

      b.样式:

        (1)css-loader : 解析css文件中代码

        (2)style-loader : 将css模块作为样式导出到DOM中

        (3)less-loader : 加载和转义less文件

        (4)sass-loader : 加载和转义sass/scss文件

        (5)postcss-loader : 使用postcss加载和转义css/sss文件

      c.脚本转换编译:

        (1)script-loader : 在全局上下文中执行一次javascript文件,不需要解析

        (2)babel-loader : 加载ES6+ 代码后使用Babel转义为ES5后浏览器才能解析

        (3)typescript-loader : 加载Typescript脚本文件

        (4)coffee-loader : 加载Coffeescript脚本文件

      d.JSON加载:

        (1)json-loader : 加载json文件(默认包含)

        (2)json5-loader : 加载和转义JSON5文件

      e.Files文件

        (1)raw-loader : 加载文件原始内容(utf-8格式)

        (2)url-loader : 多数用于加载图片资源,超过文件大小显示则以 base64 的方式把文件内容注入到代码中去

        (3)file-loader : 将文件发送到输出的文件夹并返回URL(相对路径)

        (4)jshint-loader : 检查代码格式错误

      6.加载框架:

        (1)vue-loader : 加载和转义vue组件

        (2)angualr2-template--loader : 加载和转义angular组件

        (3)react-hot-loader : 动态刷新和转义react组件中修改的部分,基于webpack-dev-server插件需先安装,然后在webpack.config.js中引用react-hot-loader

    配置loader

    modules: {
        rules: [
            {
                test: /.js$/, //匹配希望处理文件的路径
                exclude: /node_modules/, // 匹配不希望处理文件的路径
                loaders: 'xxx-loader?a=x&b=y'  //此处xxx-loader 可以简写成xxx , ?后以query方式传递给loader参数
            },
            ...
        ]
    }

    需要多loader处理的配置:

    module.exports = {
      module: {
        rules: [
          {
            test: /.css$/,
            use: [
              'style-loader',
              { loader: 'css-loader', options: { importLoaders: 1 } },
              'postcss-loader'
            ]
          }
        ]
      }
    }

    3.4 其他

    3.4.1 借助web_modules引用外部库
    有些时候,我们用到的第三方库并没有采用CommonJS或AMD规范,也没有提交到npm。这样的话,我们无法通过npm来下载,并通过require()来引用这些库。
    webpack给我们提供了一个很好的实现方式。我们可以在项目根目录下,创建一个叫做web_modules的文件夹,然后将需要用到的第三方库存放在此处。那么之后,不需要做任何设置,可以在我们的逻辑代码中使用require(
    ‘xx-lib.js’)并且使用了。

    文件组织如下:

    此时,我们就可以在业务逻辑中,大胆地使用web_modules中配置的库了,打包的时候,webpack会自动将web_modules中被用到的库封装。

    例如:

    var director = require('director')
    var Router = director.Router();

    3.4.2 去除多个文件中的频繁依赖

    当我们经常使用React、jQuery等外部第三方库的时候,通常在每个业务逻辑JS中都会遇到这些库。
    如我们需要在各个文件中都是有jQuery的$对象,因此我们需要在每个用到jQuery的JS文件的头部通过require('jquery')来依赖jQuery。 这样做非常繁琐且重复,因此webpack提供了我们一种比较高效的方法ProvidePlugin,我们可以通过在配置文件中配置使用到的变量名,那么webpack会自动分析,并且在编译时帮我们完成这些依赖的引入。

    webpack.config.js中:

    var webpack = require('webpack'); 
    ...
    plugins: [
       new webpack.ProvidePlugin({
           'Moment': 'moment',
           "$": "jquery",
           "jQuery": "jquery",
           "window.jQuery": "jquery",
           "React": "react"
       })
    ]
    ...

    这样,我们在JS中,就不需要引入jQuery等常用模块了,直接使用配置的这些变量,webpack就会自动引入配置的库。

    3.4.3 开发环境与发布环境配置

    某些情况,我们需要在页面中输出开发调试内容,但是又不想让这些调试内容在发布的时候泄露出去,那么我们可以采用DefinePlugin 来处理。

    DefinePlugin 允许创建一个在编译时可以配置的全局常量。

    配置文件:

    var webpack = require('webpack');
     
    var definePlugin = new webpack.DefinePlugin({
        __DEV__: JSON.stringify(JSON.parse(process.env.BUILD_DEV || 'false')),
        __PRERELEASE__: JSON.stringify(JSON.parse(process.env.BUILD_PRERELEASE || 'true'))
    });
     
    ...
     
    plugins: [
        definePlugin
    ]
    ...

    业务逻辑代码中写入
    按照下面的代码写入,我们就可以在我们自己设定的环境下进行更具针对性的调试。比如我们希望在开发环境下可以AJAX可以调试本地mock数据,然后在发布的时候,可以正常访问服务端数据。那么通过此种方式可以完全实现。

    if (__DEV__) {
        console.warn('Extra logging');
        //开发环境需要进行的处理
        //...
    }
     
    if (__PRERELEASE__) {
        console.log('prerelease');
        //预发环境需要进行的处理
       //...
    }

    设置环境命令

    要告诉webpack我们希望当前是什么环境,只需要在命令中写入 BUILD_DEV=1 webpck 那么webpack通过配置,就会将所有我们引用到的__DEV__变量设置为true。

    我们可以在package.json中事先定义好命令:

    "scripts": {
        "dev": "BUILD_DEV=1 webpack-dev-server --progress --colors",
        "build": "BUILD_PRERELEASE=1 webpack -p"
      }

    那么就可以避免输入冗长的命令了:

    开发时输入:

    npm run dev

    发布时输入:

    npm run build

    3.4.4 合并公共代码

    项目中,对于一些常用的组件,站点公用模块经常需要与其他逻辑分开,然后合并到同一个文件,以便于长时间的缓存。要实现这一功能,可使用CommonsChunkPlugin插件配置参照:

    var webpack = require('webpack');
    var CommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin;
     
    ...
    entry: {
       a: './index/a.js',
       b: './idnex/b.js',
       c: './index/c.js',
       d: './index/d.js'
    },
    ...
    plugins: [
       new CommonsChunkPlugin('part1.js', ['a', 'b']),
       new CommonsChunkPlugin('common.js', ['part1', 'c'])
    ]
    ...

    4 使用devtool调试

    可以通过在配置中加入devtool项,选择预设调试工具来提高代码调试质量和效率:

    • eval – 每个模块采用eval和 //@ sourceURL 来执行
    • source-map – sourceMap是发散的,和output.sourceMapFilename协调使用
    • hidden-source-map – 和source-map类似,但是不会添加一个打包文件的尾部添加引用注释
    • inline-source-map – SourceMap以DataUrl的方式插入打包文件的尾部
    • eval-source-map – 每个模块以eval方式执行并且SourceMap以DataUrl的方式添加进eval
    • cheap-source-map – 去除column-mappings的SourceMap, 来自于loader中的内容不会被使用。
    • cheap-module-source-map – 去除column-mappings的SourceMap, 来自于loader中的SourceMaps被简化为单个mapping文件

    5.webpack的构建流程是什么?从读取配置到输出文件这个过程尽量说全

    Webpack 的运行流程是一个串行的过程,从启动到结束会依次执行以下流程:

    1. 初始化参数:从配置文件和 Shell 语句中读取与合并参数,得出最终的参数;
    2. 开始编译:用上一步得到的参数初始化 Compiler 对象,加载所有配置的插件,执行对象的 run 方法开始执行编译;
    3. 确定入口:根据配置中的 entry 找出所有的入口文件;
    4. 编译模块:从入口文件出发,调用所有配置的 Loader 对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理;
    5. 完成模块编译:在经过第4步使用 Loader 翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系;
    6. 输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会;
    7. 输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统。

    在以上过程中,Webpack 会在特定的时间点广播出特定的事件,插件在监听到感兴趣的事件后会执行特定的逻辑,并且插件可以调用 Webpack 提供的 API 改变 Webpack 的运行结果。

    6. 一个常用的配置示例

    为了方便大家摘取,和补全文章中用于示例的代码片段,特将配置文件整理如下,作参考:

    配置文件:

    var webpack = require('webpack');
    var CommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin;
    var ExtractTextPlugin  = require('extract-text-webpack-plugin');
     
     
    //自定义"魔力"变量
    var definePlugin = new webpack.DefinePlugin({
        __DEV__: JSON.stringify(JSON.parse(process.env.BUILD_DEV || 'false')),
        __PRERELEASE__: JSON.stringify(JSON.parse(process.env.BUILD_PRERELEASE || 'false'))
    });
     
     
    module.exports = {
        //上下文
        context: __dirname + '/src',
        //配置入口
        entry: {
            a: './view/index/index.js',
            b: './view/index/b.js',
            vender: ['./view/index/c.js', './view/index/d.js']
        },
        //配置输出
        output: {
            path: __dirname + '/build/',
            filename: '[name].js?[hash]',
            publicPath: '/assets/',
            sourceMapFilename: '[file].map'
        },
        devtool: '#source-map',
        //模块
        module: {
            loaders: [
                {
                    //处理javascript
                    test: /.js$/,
                    exclude: /node_modules/,
                    loader: 'babel'
                }, {
                    test: /.css$/,
                    loader: ExtractTextPlugin.extract(
                        "style-loader",
                        "css-loader?sourceMap"
                    )
                }, {
                    test: /.less$/,
                    loader: ExtractTextPlugin.extract(
                        "style-loader",
                        "css-loader!less-loader"
                    )
                }, {
                    test: /.(png|jpg)$/,
                    loader: 'url-loader?limit=1024'
                }, {
                    //处理vue
                    test: /.vue$/,
                    loader: 'vue-loader'
                },
                {
                    test: /.woff(?v=d+.d+.d+)?$/,
                    loader: 'url?limit=10000&minetype=application/font-woff'
                },
                {
                    test: /.woff2(?v=d+.d+.d+)?$/,
                    loader: 'url?limit=10&minetype=application/font-woff'
                },
                {
                    test: /.ttf(?v=d+.d+.d+)?$/,
                    loader: 'url?limit=10&minetype=application/octet-stream'
                },
                {
                    test: /.eot(?v=d+.d+.d+)?$/,
                    loader: 'file'
                },
                {
                    test: /.svg(?v=d+.d+.d+)?$/,
                    loader: 'url?limit=10&minetype=image/svg+xml'
                }
            ]
     
        },
        plugins: [
            //公用模块
            new CommonsChunkPlugin('common.js', ['a', 'b']),
            //设置抽出css文件名
            new ExtractTextPlugin("css/[name].css?[hash]-[chunkhash]-[contenthash]-[name]", {
                disable: false,
                allChunks: true
            }),
            //定义全局变量
            definePlugin,
            //设置此处,则在JS中不用类似require('./base')引入基础模块, 只要直接使用Base变量即可
            //此处通常可用做,对常用组件,库的提前设置
            new webpack.ProvidePlugin({
                Moment: 'moment', //直接从node_modules中获取
                Base: '../../base/index.js' //从文件中获取
            })
        ],
        //添加了此项,则表明从外部引入,内部不会打包合并进去
        externals: {
            jquery: 'window.jQuery',
            react: 'window.React',
            //...
        }
    };

     

  • 相关阅读:
    灵活修改页面控件
    玫瑰颜色各代表什么含义?
    转:TCP端口详解
    将数据导出成text文件
    将.net布署在运行Apache服务器上
    在多线程下请注意代码的安全
    OpenWrt 设置IP地址
    WordPress 内存缓存加速插件:Batcache
    PVE 开启https 及免费SSL证书申请
    获取OpenWrt mac地址
  • 原文地址:https://www.cnblogs.com/vickylinj/p/12222685.html
Copyright © 2011-2022 走看看