webpack简介

Posted 苦海123

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了webpack简介相关的知识,希望对你有一定的参考价值。

webpack简介:

webpack是前端资源加载/打包工具,它将根据模块的依赖关系进行静态分析,然后将这些模块按照指定的规则生成对应的静态资源。在做vue项目和react项目时都会可能用到,当前最火的前端构建工具之一,把前端各种资源编译打包,最后输出:js文件、css文件、png文件,可以减少文件资源的请求。

编译原理:利用各种处理文件的loader对各种文件进行编译,根据文件后缀处理后输出新的文件,如需了解更多建议阅读相关文档:https://webpack.docschina.org/

特别强调:webpack配置文件命名为:webpack.config.js

基本使用步骤如下:

1.在命令行键入以下命令回车创建项目文件夹,也可以通过鼠标右键创建项目文件夹(命名随意):

mkdir webpackproject

2.在webpackproject文件夹中初始化一个package.json文件:

npm init -y

3.下载安装webpack及webpack-cli,命令行输入以下命令后回车:

npm install webpack webpack-cli --save-dev

4.更新目录结构:

  webpackproject
  |- package.json
 	|- index.html
 	|- /src //此目录存放开发环境代码
    	|- index.js//在此文件中键入测试代码:document.write('hello');

5.新建一个dist文件夹并将index.html文件复制到此文件夹中,如:

  webpackproject
  |- package.json
  |- /dist  //此目录用于存放生产环境代码,也就是要上线的代码
  	|- index.html
  |- /src
    |- index.js

6.在命令行执行以下命令回车,此时会发现dist文件夹中新增main.js文件,此文件就是src下面的index.js文件压缩版(以后在修改完src中的代码后再执行此命令,dist中的代码会自动更新):

webpack 或 npx webpack --config webpack.config.js

此方式不是很方便,可以在package.json文件中配置一个快捷启动方式:在scripts键中添加:“build”: “webpack”,这里的build可以是任意没有意义的值,之后启动时在命令行输入:npm run build即可,build 需要保持一致。

7.使用webpack配置文件:有的项目中会用到webpack配置文件,这比直接在终端输入命令高效的多,基本配置如下:

	 // webpack文件主配置:
    module.exports = {
        mode: 'production', //启用webpack内部在相应环境下的优化,其值还有:development和none,实际是控制dist文件夹下文件是否压缩。
        entry: { //---entry配置入口文件,指示 webpack 使用哪个模块来作为构建的基础;也可以是多入口来创建多页面应用程序,这里介绍单页面应用程序;
            main: './src/main.js', //---main是默认入口,即veu项目中的main.js文件,main.js文件用来监听index.html文件中的盒子,并将app.vue文件的渲染结果返回给index.html文件中的这个盒子。
            vendor: './src/vendor.js' //第三方库,会将main.js和vendor.js文件分开,这里可以不用配置此项。
        }, //entry后面还可以直接跟字符串路径或数组路径,如:entry: './src/main.js'和entry: ['./src/file1.js', './src/file2.js']
        output: { //---文件出口,将打包好的文件命名后输出
            filename: './build.js', //---指定最终生成的js文件名
            path: path.join(__dirname, 'dist') //----打包好的文件路径,最好是绝对路径;这里代表当前目录的上一级的dist目录;注意引入path模块
        },
        module: {
            rules: [ //------webpack默认只能认识javascript和json文件,更多的loader可以用于配置处理更多的一类文件,此配置为loader配置,这里可以用更早的loaders:[],功能和rules一样,不推荐;需要注意这些lodaer需要install且有的有依赖也要install。
                { //test是用于检测文件类型的;use是指定使用哪个loader,更早版本可以使用loader代替use但是不推荐。
                    test: /\\.css$/, //-----处理css文件需要引入多个loader,如style-loader和css-loader中间可用!分开,test用于检测文件后缀
                    use: 'style-loader!css-loader' //-----这里是有顺序的,不能反过来使用;use还可以接数组,数组的每一项配置对应的loader如:
                        // use: [
                        //     { loader: 'style-loader' },
                        //     {
                        //         loader: 'css-loader',
                        //         options: {
                        //             modules: true
                        //         }
                        //     }
                        // ]
                },
                {
                    test: /\\.(jpg|svg|png|gif)$/, //----url-loader?limit=4096$name=[name].[ext]处理后缀为jpg、svg的图片文件,这里可以处理很多种格式的图片文件,只需要将文件后缀配置到这里即可。
                    use: 'url-loader?limit=4096$name=[name].[ext]', //[name].[ext]内置提供,[name]用来设置文件名,[ext]用于设置文件后缀名;limit用于设置当文件大于某字节时以base64格式输出,问号后面可以以options方式输出(废弃,不推荐),(新版中采用file-loader)如:
                    //options方式输出配置,已经废弃:
                    //options:{
                    //     limit:4096,
                    //     name:[name].[ext]
                    //}
                },
                {
                    test: /\\.js$/, //----bable-loader处理后缀为js的文件
                    use: 'babel-loader',
                    exclude: /node-modules/, //---排除某文件下的文件不被处理,这里一般排除第三方资源,如node-modules文件夹中的文件
                    options: {//注意废弃问题
                        presets: ['es2015'], //关键字,这里配置的是解析es6语法
                        plugins: ['transform-runtime'], //函数
                    }
                },
                {
                    text: /\\.vue$/, //解析vue文件配置:
                    use: 'vue-loader' //vue-template-compiler是代码上的依赖
                },
                {
                    test: /\\.txt$/,
                    use: 'raw-loader'
                }
            ]
        },
        plugins: [ //配置插件,执行范围更广的任务,如:打包优化,资源管理,注入环境变量。
            new htmlWebpackPlugin({ //将src下的template属性描述的文件移动到当前output.path的配置目录下并生成html文件,htmlWebpackPlugin是一个模块,需要引入:html-webpack-plugin模块(应用程序生成一个 HTML 文件,并自动注入所有生成的 bundle)
                template: './src/index.html'
            })
        ]
    };
    
    //下面是新版webpack基本的webpack.ocnfig.js文件代码:
    const htmlWebpackPlugin = require('html-webpack-plugin');
    const path = require('path')
    module.exports = {
        mode: 'production',
        entry: {
            main: './src/main.js',
            vendor: './src/vendor.js'
        },
        output: {
            filename: './build.js',
            path: path.join(__dirname, 'dist')
        },
        module: {
            rules: [{
                    test: /\\.css$/,
                    use: [
                        'style-loader',
                        'css-loader'
                    ]
                },
                {
                    test: /\\.(jpg|svg|png|gif)$/,
                    use: ['file-loader']
                },
                {
                    test: /\\.js$/,
                    use: 'babel-loader',
                    exclude: /node-modules/
                        // options: {
                        //     presets: ['es2015'],
                        //     plugins: ['transform-runtime'],
                        // }
                },
                {
                    text: /\\.vue$/,
                    use: 'vue-loader'
                },
                {
                    test: /\\.(woff|woff2|eot|ttf|otf)$/,
                    use: [
                        'file-loader'
                    ]
                },
                {
                    test: /\\.txt$/,
                    use: 'raw-loader'
                },
                {
                    test: /\\.(csv|tsv)$/,
                    use: [
                        'csv-loader'
                    ]
                },
                {
                    test: /\\.xml$/,
                    use: [
                        'xml-loader'
                    ]
                }
            ]
        },
        plugins: [
            new htmlWebpackPlugin({
                template: './src/index.html'
            })
        ]
    };

如果配置完此文件,在命令行直接键入npm run build等启动命令,则会自动生成dist文件夹及里面文件,这样在做一个项目的时候就快捷多了,同时也会处理更多不同格式的文件(利用不同的loader)。

常见处理各种资源的loader总结:

在javascript模块中引入其他文件,需要安装对应的loader,之后在将这些loader配置到对应的位置,如:

资源loader及描述
css文件style-loader 和 css-loader;用于解析通过import导入js文件的css文件等
images图像file-loader;解析background和icon等图像文件
fonts字体file-loader 和 url-loader 可以接收并加载任何文件,这里采用其中一种就可以解析fonts文件
数据文件csv-loader和xml-loader解析json、xml等数据
vue文件vue-loader,处理vue组件

html-webpack-plugin:

用于生成一个HTML5文件并将这个文件打包到dist目录下的插件,使用时只需要将其添加到webpack配置文件中(使用过此插件后dist文件夹中生成的index.html文件会引用dist文件下的main.js文件,此main.js文件会包含css等),如:

	const path = require('path');
    const HtmlWebpackPlugin = require('html-webpack-plugin');//需要安装
    
    module.exports = {
        entry: {
            app: './src/index.js'
        },
        output: {
            filename: '[name].bundle.js',
            path: path.resolve(__dirname, 'dist')
        },
        plugins: [
            new HtmlWebpackPlugin({
                title: 'index'
            })
        ],
    };

clean-webpack-plugin:

用于清除dist目录中的旧文件,在每次构建时都会清除之前构建的dist目录下的文件,这样dist文件夹就不会显得很杂乱了,如:

	const path = require('path');
    const CleanWebpackPlugin = require('clean-webpack-plugin'); //注意需要安装
    module.exports = {
        entry: {
            app: './src/index.js',
            print: './src/print.js'
        },
        plugins: [
            new CleanWebpackPlugin()
        ],
        output: {
            filename: '[name].bundle.js',
            path: path.resolve(__dirname, 'dist')
        }
    };

source map:

在开发环节中,webpack会将不同的模块最终打包到一起,此时如果某个模块有错误,这个错误只会显示在打包后的总文件中,此时想要修改未打包前的原文件,那么就很难找到错误所在了。当然webpack提供了source map可以将编译好的代码映射到源码中,这样就可以找到错误所在了,具体如:

	module.exports = {
        mode: 'development', //1.将mode设置为开发环境
        entry: {
            app: './src/index.js'
        },
        devtool: 'inline-source-map', //2.devtool属性设置为inline-source-map
        output: {
            filename: 'index.js',
            path: path.resolve(__dirname, 'dist')
        }
    };
    //3.此时如果某个文件有错误,那么在控制台就会清楚的显示到某文件某行出现错误。

自动编译:

webpack提供了几种自动编译代码的配置,当代码被修改后会自动编译,此配置有:webpack watch mode(webpack 观察模式)、webpack-dev-server、webpack-dev-middleware,常用webpack-dev-server,它们具体使用方法如下:

	webpack watch mode:(缺点:浏览器不能被自动刷新)
    1.package.json文件scripts中添加:"watch": "webpack --watch"
    2.在终端输入:npm run watch 
    3.不要关闭终端,当文件发生修改并保存后,在终端就会看到文件被修改了
    
    
    webpack-dev-server:
    1.npm install --save-dev webpack-dev-server 终端下载并安装
    2.在webpack.config.js文件module.exports中添加如下代码,表示搜索栏输入搜索后从什么位置查找文件:
    devServer: {
        contentBase: './dist'
    }
    3.此时当代码发生修改在浏览器端就可以实现修改效果,但是输出文件是不会被修改的,若想要输出的文件也被修改,那么就要在package.json文件scripts中添加:"start": "webpack-dev-server --open"
    4.在终端输入:npm start ,代码被编译并重新加载到浏览器
    
    
    webpack-dev-middleware:它是一个封装器,可以将webpack处理过的文件发送到服务器,比较繁琐,不推荐使用。
    1.npm install --save-dev webpack-dev-middleware 终端下载安装
    2.webpack.config.js文件output中添加:publicPath: '/'  来确保middleware中间件能被启动
    3.在服务端脚本使用 publicPath 使文件资源能被浏览器访问到
    4.在服务端脚本use中间件:webpackDevMiddleware,如下:
    app.use(webpackDevMiddleware(compiler, {
      publicPath: config.output.publicPath
    }));
    5.package.json文件scripts中添加:"server": "node server.js"
    6.在终端输入:npm run server 后在浏览器访问指定地址,就会看到webpack运行。

注意:在开启自动编译代码后,有的编辑器会有安全写入配置,此功能会影响自动编译,此时需要将这个编辑器的此功能禁用掉,不同的编辑器方法不同,建议百度。

HMR模块热替换:

允许在运行时不完全刷新而更新所有类型模块,可以提高开发效率,其具体使用如下(这里采用webpack-dev-server作为基础):

	1.const webpack = require('webpack'); 引入webpack自身来使用内置模块
    2.在webpack.config.js文件中配置:devServer对象中添加:hot: true ;plugins对象中添加:new webpack.HotModuleReplacementPlugin()
    3.在index.js打包后的文件中输入:
    if (module.hot) {
        module.hot.accept('./print.js', function() {
            printMe();
        })
    }

webpack-merge分离配置webpack.config.js:

实际中会将开发环境和生产环境的webpack文件分离开,但是他们有着相同的部分,此时可以将webpack配置文件分离开,在不同的配置文件引入相同的部分配置文件即可,具体如:

	//1.npm install --save-dev webpack-merge  下载安装webpack-merge
    //2.在webpackproject项目文件夹下,新建若干webpack配置文件,并将之前的 webpack.config.js删除:
    //|- webpack.common.js //用于写公共配置的文件,配置entry、output、plugins等,如:
    const path = require('path');
    const CleanWebpackPlugin = require('clean-webpack-plugin');
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    module.exports = {
        entry: {
            app: './src/index.js'
        },
        plugins: [
            new CleanWebpackPlugin(['dist']),
            new HtmlWebpackPlugin({
                title: 'Production'
            })
        ],
        output: {
            filename: '[name].bundle.js',
            path: path.resolve(__dirname, 'dist')
        }
    };
    
    |- webpack.dev.js //用于写开发环境的配置文件,需要引入common配置文件和webpack-merge模块,如:
    const merge = require('webpack-merge');
    const common = require('./webpack.common.js');
    module.exports = merge(common, {
        mode: 'development',
        devtool: 'inline-source-map',
        devServer: {
            contentBase: './dist'
        }
    });
    
    |- webpack.prod.js //用于写生产环境的配置文件,需要引入common配置文件和webpack-merge模块,如:
    const merge = require('webpack-merge');
    const common = require('./webpack.common.js');
    module.exports = merge(common, {
        mode: 'production',
    });
    
    //3.将package.json文件scripts中的配置修改为启动上面分离开的webpack配置文件,在终端只需npn 对应配置 即可启动指定webpack配置,如:
    "scripts": {
        "start": "webpack-dev-server --open --config webpack.dev.js", //通过npm start启动webpack.dev.js
        "build": "webpack --config webpack.prod.js" //通过npm build启动webpack.prod.js
    }

代码分离:

此特性能够把代码分离到不同的 bundle 中,按需加载,可以提高效率;常见的代码分离有三种方式:入口起点、防止重复、动态导入,下面将简单介绍一下:

	 //1.入口起点(不推荐):说白了就是在entry中配置多个入口,优点是比较简单直观,缺点是比较繁琐,需要手动配置且存在隐患,如:
    module.exports = {
        entry: {
            index: './src/index.js',
            another: './src/another.js'
        },
        output: {
            filename: '[name].bundle.js',
            path: path.resolve(__dirname, 'dist')
        }
    };//此时从新构建会生成多个js文件在dist文件夹中,但是会将重复的模块引入到各个bundle中,且不能动态的将核心应用程序逻辑代码拆封开。
    
    //2.防止重复(不推荐):SplitChunksPlugin插件可以将公共的依赖模块提取到同一个chunk中,这样就可以去重;其配置是在入口起点的方式上加上以下配置:
    module.exports = {
        entry: {
            index: './src/index.js',
            another: './src/another.js'
        },
        output: {
            filename: '[name].bundle.js',
            path: path.resolve(__dirname, 'dist')
        },
        // 新添加的配置代码:
        optimization: {
            splitChunks: {
                chunks: 'all'
            }
        }
    };//此时重新构建会将重复的依赖删除,webpack提供了mini-css-extract-plugin(将CSS从主程序中分离)、bundle-loader(分离代码和延迟加载生成的bundle)、promise-loader(使用了promise API,类似bundle-loader)
    
    //3.动态导入(推荐):动态拆封代码时,webpack提供了动态导入,具体如下:
    module.exports = {
        entry: {
            index: './src/index.js',
        },
        output: {
            filename: '[name].bundle.js',
            chunkFilename: '[name].bundle.js',//配置chunkFilename
            path: path.resolve(__dirname, 'dist')
        }
    };//此时就可以通过一个入口分离,且不会重复;

预加载和预取:

webpack提供了预加载相关指令,在声明 import 时,使用内置的这些指令:prefetch(预取),将来某些导航下可能需要的资源、preload(预加载),当前导航下可能需要资源,其用法如下:

	 import(/* webpackPrefetch: true */ 'LoginModal'); //会生成 <link rel="prefetch" href="login-modal-chunk.js"> 并追加到页面头部,指示着浏览器在闲置时间预取 login-modal-chunk.js 文件。
    
    
    import(/* webpackPreload: true */ 'ChartingLibrary');//在请求 ChartComponent.js 的同时,还会通过 <link rel="preload"> 请求 charting-library-chunk。

懒加载:

懒加载或按需加载是优化网页很好的功能,这里只介绍相关框架的懒加载内库:

React: https://reactrouter.com/web/guides/code-splitting

Vue:https://alexjover.com/blog/lazy-load-in-vue-using-webpack-s-code-splitting/

AngularJS: 百度查

缓存:

通过缓存,可以降低网络流量,使网站加载速度更快,然而当修改完代码后,文件名没有修改的情况下,浏览器会认为没有修改,此时更新的代码就不会被利用,而是继续使用的缓存文件;当然webpack解决了这一问题:简单的配置就能使被webpack编译的新文件被缓存并可以请求到新文件,其原理是利用动态设置文件名而解决缓存问题的,如:

	module.exports = {
        entry: './src/index.js',
        plugins: [
            new CleanWebpackPlugin(['dist']),
            new HtmlWebpackPlugin({
                title: 'test'
            })
        ],
        output: {
            filename: '[name].[contenthash].js', //动态生成文件名的方式来解决缓存问题
            path: path.resolve(__dirname, 'dist')
        }
    };

提取索引模板:

webpack 提供一个优化功能代码分离的功能,可使用 optimization.runtimeChunk 选项将 runtime 代码拆分为一个单独的 chunk。将其设置为 single 来为所有 chunk 创建一个 runtime bundle,其配置如下:

	module.exports = {
        entry: './src/index.js',
        plugins: [
            new CleanWebpackPlugin(['dist']),
            new HtmlWebpackPlugin({ title: 'Caching' })
        ],
        output: {
            filename: '[name].[contenthash].js',
            path: path.resolve(__dirname, 'dist')
        },
        optimization: {
            runtimeChunk: 'single' //配置runtimeChunk: 'single'
        }
    };

实际中会将第三方的包也分离开,这样可以避免第三方包的频繁修改,减少请求,其配置如:

	module.exports = {
        entry: './src/index.js',
        plugins: [
            new CleanWebpackPlugin(['dist']),
            new HtmlWebpackPlugin({ title: 'Caching' })
        ],
        output: {
            filename: '[name].[contenthash].js',
            path: path.resolve(__dirname, 'dist')
        },
        optimization: {
            runtimeChunk: 'single', //配置runtimeChunk: 'single'
            splitChunks: { //继续配置此项实现分离第三方包
                cacheGroups: {
                    vendor: {
                        test: /[\\\\/]node_modules[\\\\/]/,
                        name: 'vendors',
                        chunks: 'all'
                    }
                }
            }
        }
    };

模块标识符:

模块标识符是用来解决vendor bundle不被修改的功能,使用此功能需要配置如下配置:

	const path = require('path');
    const webpack = require('webpack')以上是关于webpack简介的主要内容,如果未能解决你的问题,请参考以下文章

Webpack 简介

webpack

webpack源码之ast简介

Vue报错:Uncaught TypeError: Cannot assign to read only property 'exports' of object 的解决方法(代码片段

Android 逆向Linux 文件权限 ( Linux 权限简介 | 系统权限 | 用户权限 | 匿名用户权限 | 读 | 写 | 执行 | 更改组 | 更改用户 | 粘滞 )(代码片段

SpringCloud系列十一:SpringCloudStream(SpringCloudStream 简介创建消息生产者创建消息消费者自定义消息通道分组与持久化设置 RoutingKey)(代码片段