Webpack学习

Webpack学习笔记

前端模块化

在了解Webpack之前,必须说一下前端模块化的概念。
随着前端开发规模,以及代码逻辑复杂性的提高,在大型项目的开发中,大量forPage的js文件引用不仅显得很蠢且冗余,也给后期代码维护带来的很大的成本。所以引入了模块化开发的概念。
模块化开发,一个模块就是一个实现特定(且相对独立)功能的文件,有了模块我们就可以更方便的使用别人的代码,要用什么功能就加载什么模块。

模块化开发的四点好处

  1. 避免变量污染与命名冲突
  2. 提高代码(模块)的复用率
  3. 提高可维护性
  4. 依赖关系的统一管理

Webpack的使用场景

目前,前端通用的模块化开发方式,以及目前我们项目组使用的Vue框架,以及Scss,less等CSS预处理器,这些改进确实大大的提高了我们的开发效率,但是利用它们开发的文件往往需要进行额外的处理才能让浏览器识别,而手动处理又是非常繁琐的,这就为Webpack类的工具的出现提供了需求。

现在可以回答这个问题了,什么是Webpack?

用我自己的理解方式来说,Webpack就是项目各模块的打包工具。它通过分析项目结构,寻找各模块之间的依赖关系,将那些浏览器无法直接识别的文件(如.vue),转换并统一打包成浏览器可识别的文件(如.js

Webpack的工作方式?

把项目当做一个整体,通过一个给定的主文件/入口文件(如:main.js),Webpack将从这个文件开始找到你的项目的所有依赖文件,使用loaders处理它们,最后打包为一个(或多个)浏览器可识别的JavaScript文件。

Webpack学习

Webpack的安装

//全局安装webpack
npm i -g webpack
//安装到项目目录
npm i --save-dev webpack

Webpack的配置项

1. 生成Source Maps(方便调试)

通过打包完成的js文件,在调试的时候简直是灾难,难以找出出错位置与对应的代码位置,而Source Maps 就可以为我们解决这个问题。它提供了一种对应打包文件和源文件的方法,来方便我们进行调试。
Webpack的配置文件中配置Source Maps,需要配置devtool,共有四种配置选项:

devtool
配置选项
说明
source-map在一个单独的文件中产生一个完整且功能完全的文件。这个文件具有最好的source map,但是它会减慢打包速度
cheap-module-source-map在一个单独的文件中生成一个不带列映射的map,不带列映射提高了打包速度,但是也使得浏览器开发者工具只能对应到具体的行,不能对应到具体的列(符号),会对调试造成不便
eval-source-map使用eval打包源文件模块,在同一个文件中生成干净的完整的source map。这个选项可以在不影响构建速度的前提下生成完整的sourcemap,但是对打包后输出的JS文件的执行具有性能和安全的隐患。在开发阶段这是一个非常好的选项,在生产阶段则一定不要启用这个选项
cheap-module-eval-source-map这是在打包文件时最快的生成source map的方法,生成的Source Map 会和打包后的JavaScript文件同行显示,没有列映射,和eval-source-map选项具有相似的缺点

上述选项从上到下打包速度越来越快,对打包后文件的执行影响也越来越大,因此在中小型项目中,eval-source-map是一个很好的选项,注意只有在dev环境下使用它们,在prod环境下需要关闭该选项。

2. 实现热更新

Webpack提供一个可选的本地开发服务器webpack-dev-server,这个本地服务器基于node.js构建

webpack-dev-server
配置选项
说明
contentBase默认webpack-dev-server会为根文件夹提供本地服务器,如果想为另外一个目录下的文件提供本地服务器,应该在这里设置其所在目录
port设置默认监听端口,如果省略,默认为”8080“
inline设置为true,当源文件改变时会自动刷新页面
historyApiFallback在开发单页应用时非常有用,它依赖于HTML5 history API,如果设置为true,所有的跳转将指向index.html

3. Loaders

Webpack相当重要的功能,通过使用不同的loader,Webpack可以使用外部工具来处理不同格式的文件,比如scsscss,(ES6,ES7的JS文件)转为现代浏览器兼容的JS文件
Loaders需要单独安装并且需要在webpack.xxx.config.js中的modules关键字下进行配置

Loaders
配置选项
说明
test一个用以匹配Loaders所处理文件的拓展名的正则表达式(必须)
loaderloader的名称(必须)
include/exclude手动添加必须处理的文件(文件夹)或屏蔽不需要处理的文件(文件夹)(可选);
queryLoaders提供额外的设置选项(可选)

介绍之Babel

Babel其实是一个编译JavaScript的平台,它可以编译代码帮你达到以下目的:

  • 让你能使用最新的JavaScript代码(ES6,ES7...),而不用管新标准是否被当前使用的浏览器完全支持;
  • 让你能使用基于JavaScript进行了拓展的语言,比如ReactJSX

由于Babel的配置选项非常多,经常会把babel的配置选项放在.babelrc的配置文件中

介绍之css-loaderstyle-loader

二者处理的任务不同,css-loader使你能够使用类似@importurl(...)的方法实现 require()的功能,style-loader将所有的计算后的样式加入页面中,二者组合在一起使你能够把样式表嵌入Webpack打包后的JS文件中

  • 关于CSS modules
    把JS的模块化思想带入CSS中来,通过CSS模块,所有的类名,动画名默认都只作用于当前模块。Webpack对CSS模块化提供了非常好的支持,只需要在CSS loader中进行简单配置即可,然后就可以直接把CSS的类名传递到组件的代码中,这样做有效避免了全局污染。具体代码如下
module.exports = {

    ...

    module: {
        rules: [
            {
                test: /(\.jsx|\.js)$/,
                use: {
                    loader: "babel-loader"
                },
                exclude: /node_modules/
            },
            {
                test: /\.css$/,
                use: [
                    {
                        loader: "style-loader"
                    }, {
                        loader: "css-loader",
                        options: {
                            modules: true, // 指定启用css modules
                            localIdentName: '[name]__[local]--[hash:base64:5]' // 指定css的类名格式
                        }
                    }
                ]
            }
        ]
    }
};

介绍之CSS预处理器

SassLess 之类的预处理器是对原生CSS的拓展,它们允许你使用类似于variables, nesting, mixins, inheritance等不存在于CSS中的特性来写CSS,CSS预处理器可以这些特殊类型的语句转化为浏览器可识别的CSS语句,

你现在可能都已经熟悉了,在Webpack里使用相关load请输入代码ers进行配置就可以使用了,以下是常用的CSS 处理Loaders:

  • Less Loader
  • Sass Loader
  • Stylus Loader

4. 插件(Plugins)

插件(Plugins)是用来拓展Webpack功能的,它们会在整个构建过程中生效
注意PluginsLoaders的区别:

  • Plugins是在整个构建过程中生效的,拓展Webpack功能的(比如压缩打包后的文件,添加版权声明等等)
  • Loaders是在文件打包过程中加入的外部脚本/工具,用于处理特殊的源文件(.vue,JSXscss,Less

上一份比较完整的conf代码:

// webpack.prd.config.js
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    entry: __dirname + "/src/main.js", //已多次提及的唯一入口文件
    output: {
        path: __dirname + "/dist",
        filename: "bundle.js"
    },
    devtool: 'null', //注意修改了这里,这能大大压缩我们的打包代码
    devServer: {
        contentBase: "./public", //本地服务器所加载的页面所在的目录
        historyApiFallback: true, //不跳转
        inline: true,
        hot: true
    },
    module: {  //Loaders配置
        rules: [{
            test: /(\.jsx|\.js)$/,
            use: {
                loader: "babel-loader"
            },
            exclude: /node_modules/
        }, {
            test: /\.css$/,
            use: ExtractTextPlugin.extract({
                fallback: "style-loader",
                use: [{
                    loader: "css-loader",
                    options: {
                        modules: true
                    }
                }, {
                    loader: "postcss-loader"
                }],
            })
        }]
    },
    plugins: [  //插件配置
        new webpack.BannerPlugin('版权所有,翻版必究'),
        new HtmlWebpackPlugin({
            template: __dirname + "/app/index.tmpl.html" //new 一个这个插件的实例,并传入相关的参数
        }),
        new webpack.HotModuleReplacementPlugin() //热加载插件
    ],
};

感谢zhangwang大佬的入门 Webpack,看这篇就够了,本篇学习攻略大部分来源于他的文章指导,感谢~

相关推荐