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'); //会生成  并追加到页面头部,指示着浏览器在闲置时间预取 login-modal-chunk.js 文件。
    
    
    import(/* webpackPreload: true */ 'ChartingLibrary');//在请求 ChartComponent.js 的同时,还会通过  请求 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');
    const CleanWebpackPlugin = require('clean-webpack-plugin');
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    module.exports = {
        entry: './src/index.js',
        plugins: [
            new CleanWebpackPlugin(['dist']),
            new HtmlWebpackPlugin({
                title: 'Caching'
            }),
            new webpack.HashedModuleIdsPlugin() //配置项
        ],
        output: {
            filename: '[name].[contenthash].js',
            path: path.resolve(__dirname, 'dist')
        },
        optimization: {
            runtimeChunk: 'single',
            splitChunks: {
                cacheGroups: {
                    vendor: {
                        test: /[\\/]node_modules[\\/]/,
                        name: 'vendors',
                        chunks: 'all'
                    }
                }
            }
        }
    };

创建library:

可以将自己开发的包进行打包,其基本用法如:

	 //1. npm init -y 终端初始化一个项目文件夹
    //2. npm install --save-dev webpack lodash 终端下载安装webpack和lodash
    //3. 编写自己的包
    //4. webpack.config.js基本配置:
    var path = require('path');
    module.exports = {
        entry: './src/index.js',
        output: {
            path: path.resolve(__dirname, 'dist'),
            filename: 'webpack-name.js'//自定义name值
          	library: 'webpackName'
        },
        externals: {
            lodash: {
                commonjs: 'lodash',
                commonjs2: 'lodash',
                amd: 'lodash',
                root: '_'
            }
        }
    };
    //5.将包添加到package.json文件main字段,如:
    "main": "dist/webpack-numbers.js"

预设依赖shim:

webpack默认是无法识别一些第三方库的全局依赖或变量,但是shim可以解决这一问题,具体如:

	//shim预设全局变量:想要将模块依赖改为全局变量依赖就要用到 ProvidePlugin 插件,如:
    const webpack = require('webpack');
    module.exports = {
        entry: './src/index.js',
        output: {
            filename: 'bundle.js',
            path: path.resolve(__dirname, 'dist')
        },
        plugins: [
            new webpack.ProvidePlugin({
                _: 'lodash'//告诉webpack如果用到以_变量的模块,将lodash package引入
              	//join: ['lodash', 'join'] //暴露模块单个导出
            })
        ]
    };
    
    
    //细粒度shim:指的是一些依赖的this指向window对象,而在commonjs中此时this指向module.exports,为了this指向window,可以配置如下:
    module: {
        rules: [{
            test: require.resolve('index.js'),
            use: 'imports-loader?this=>window' //配置后将原本指向module.exports的this重新指向为window
        }]
    }
    
    
    //全局export:将全局变量作为一个普通模块导出,利用exports-loader,如:
    module: {
        rules: [{
                test: require.resolve('index.js'),
                use: 'imports-loader?this=>window'
            },
            {
                test: require.resolve('globals.js'),
                use: 'exports-loader?file,parse=helpers.parse'
            }
        ]
    }
    
    
    //加载 polyfill:可以使用原生功能,配置如下:
    //1.npm install --save babel-polyfill 下载安装babel-polyfill
    //2.使用import将babel-polyfill导入src/index.js文件
    //3.npm install --save whatwg-fetch 继续下载安装whatwg-fetch
    //4.import 'babel-polyfill';import 'whatwg-fetch' 到src/polyfills.js文件,并将src/index.js文件中babel-polyfill去掉
    //5.在webpack.config.js文件中新增入口 polyfills: './src/polyfills.js';新增动态输入文件名:filename: '[name].bundle.js'
    //6.此时可以在dist/index.html文件head标签中新增一下逻辑就可以根据以下逻辑来加载polyfill
    <script>
        var modernBrowser = (
            'fetch' in window &&
            'assign' in Object
        );
        if (!modernBrowser) {
            var scriptElement = document.createElement('script');
    
            scriptElement.async = false;
            scriptElement.src = '/polyfills.bundle.js';
            document.head.appendChild(scriptElement);
        }
    </script>

渐进式网络应用程序:

一种在离线环境下继续运行的功能,类似于native app,其原理是通过Service Workers 的 web 技术来实现。其具体用法如下:

	 //1.npm install http-server --save-dev  安装http-server
    //2.修改package.json文件scripts中配置为:"build": "webpack"和"start": "http-server dist"
    //3.终端输入:npm run build 构建项目、npm start 启动服务,此时在停止服务的情况下是无法做到离线运行的,想要做到离线运行,就得继续下一步:
    //4.npm install workbox-webpack-plugin --save-dev  安装workbox-webpack-plugin,并在webpack.config.js文件中引入:const WorkboxPlugin = require('workbox-webpack-plugin');
    //5.配置webpack.config.js文件中plugins项如下:
    plugins: [
        new CleanWebpackPlugin(['dist']),
        new HtmlWebpackPlugin({}),
        new WorkboxPlugin.GenerateSW({//开启离线可运行配置
            clientsClaim: true,
            skipWaiting: true
        })
    ]
    //6.终端继续输入:npm run build 可以看到新增:service-worker.js和precache-manifest.b5ca1c555e832d6fbf946fd29d27eb.js文件,则表示Service Worker创建成功
    //7.在index.js文件总添加如下代码用以注册Service Worker:
    if ('serviceWorker' in navigator) {
        window.addEventListener('load', () => {
            navigator.serviceWorker.register('/service-worker.js').then(registration => {
                console.log('SW registered: ', registration);
            }).catch(registrationError => {
                console.log('SW registration failed: ', registrationError);
            });
        });
    }
    //8.在此运行 npm run build 构建项目,之后在运行 npm start 启动项目。
    //9.到浏览器通过http://localhost:8080访问并查看控制台console是否存在:SW registered,存在则表示成功
    //10.停止server进行测试,如果浏览器支持Service Worker则可以看到程序运行正常。

处理TypeScript:

TypeScript 是 JavaScript 的超集,增加了类型系统,可以编译为 JavaScript 代码。下面将介绍如何将 webpack 和 TypeScript 进行集成,其基础配置如下:

	 //1.npm install --save-dev typescript ts-loader  下载安装typescript和ts-loader
    //2.在某个项目文件夹中新增:tsconfig.json配置文件,其配置如下:
    {
      "compilerOptions": {
        "outDir": "./dist/",
          "sourceMap": true,//用以开启source map
        "noImplicitAny": true,
        "module": "es6",
        "target": "es5",
        "jsx": "react",
        "allowJs": true
      }
    }//这里只是简单配置,如果想要了解更多关于tsconfig.json配置,可阅读:https://www.typescriptlang.org/docs/handbook/tsconfig-json.html
    //3.在webpack.config.js文件rules中新增处理ts的配置如下:
    module.exports = {
        entry: './src/index.ts',//入口ts文件并处理里面依赖的ts和tsx文件,处理后输出到:bundle.js文件中
        devtool: 'inline-source-map',//配置source map
      	module: {
            rules: [{
                test: /\.tsx?$/, //处理ts
                use: 'ts-loader',
                exclude: /node_modules/
            }]
        },
        resolve: {
            extensions: ['.tsx', '.ts', '.js']
        },
        output: {
            filename: 'bundle.js',
            path: path.resolve(__dirname, 'dist')
        }
    };

在使用typescript时,可能会引用第三方library,此时需要安装对应第三方library,如typescript中lodash为:@types/lodash,需要安装的则为:npm install --save-dev @types/lodash;更多配置查阅:https://devblogs.microsoft.com/typescript/the-future-of-declaration-files-2/

typescript中导入其他资源:

在 TypeScript 中使其他资源,需要告知TypeScript导入资源类型,具体做法如下:

	 //1.在项目中创建一个custom.d.ts文件(用于自定义类型声明),如配置.svg文件配置如下:
    declare module "*.svg" {
      const content: any;
      export default content;
    }//配置其他CSS, SCSS, JSON 资源方法类似。

环境变量:

开发环境和生产环境之间的webpack.config.js存在差异,通过环境变量就可以消除差异。在webpack命令行中配置环境变量用到–env,配置好的环境变量可以在webpack.config.js文件中被访问到,如:

	//配置环境变量:
    webpack --env.number = '2'
    
    //接收环境变量:
    module.exports = env => {
      console.log(env.number);
    }

构建性能:

无论在开发环境还是生产环境,都应给提高构建性能以达到最佳效果。性能优化可以从以下几点出发:

	1.更新webpack及node.js、npm等到最新版本,新版本中可以提高解析速度。
    2.仅对必要的模块使用loader,使用include将loader应用在实际需要转换的模块所指路径,如:
    rules: [{
        test: /\.js$/,
        include: path.resolve(__dirname, 'src'),
        loader: 'babel-loader'
    }]
    3.loader或plugin都有自己的启动时间,尽量少用。
    4.从解析角度出发减少文件系统调用次数、关闭不用的resolve.symlinks、
    5.使用 DllPlugin将更改不频繁的代码单独编译
    6.减小编译结果的整体大小
    7.通过thread-loader将非常耗资源的loader分给一个worker pool
    8.通cache-loader启动持久化缓存;使用package.json中"postinstall" 清除缓存目录
    9.增量编译:使用 webpack 的 watch mode;使用 watchOptions.poll 来增加轮询的间隔
    10.在内存中编译:webpack-dev-server、webpack-hot-middleware、ebpack-dev-middleware
    11.小化每个增量构建步骤中,从 stats 对象获取的数据量
    12.某些工具只能在生产环境才会有作用,尽量避免在开发环境使用这类工具:TerserPlugin、[hash]/[chunkhash]、AggressiveMergingPlugin等
    13.最小化 entry chunk
    14.避免额外的优化步骤
    15.输出结果不携带路径信息
    16.使用TypeScript loader内置watch mode API
    17.尽量少使用source map 
    18.还有很多做优化的方面,这里不再做过多介绍。

内容安全策略:

webpack 能够为其加载的所有脚本添加 nonce,启用此功能需在入口文件配置__webpack_nonce__变量,且应该为每个页面视图添加唯一的hash的nonce,`、nonce 应该是一个 base64 编码的字符串。

开发 - Vagrant:

使用Vagrant在虚拟机上运行开发环境且运行webpack,步骤如下:

	1.确保 Vagrantfile 拥有一个静态 IP
    Vagrant.configure("2") do |config|
      config.vm.network :private_network, ip: "10.10.10.61"
    end
    2.项目中安装 webpack 和 webpack-dev-server:
    npm install --save-dev webpack webpack-dev-server
    3.确保有webpack.config.js 配置文件,配置代码如:
    module.exports = {
      context: __dirname,
      entry: './app.js'
    };
    4.确保有一个index.html文件,且有一script标签(src指向你的bundle)
    5.创建一个app.js文件
    6.webpack-dev-server --host 0.0.0.0 --public 10.10.10.61:8080 --watch-poll 启动server

配合 nginx 的高级用法:

为更好模拟类生产环境,可采用nginx代理webpack-dev-server,nginx配置如下:

	server {
      location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        error_page 502 @start-webpack-dev-server;
      }
    
      location @start-webpack-dev-server {
        default_type text/plain;
        return 502 "Please start the webpack-dev-server first.";
      }
    }
    
    webpack-dev-server 启动命令可修改为:webpack-dev-server --public 10.10.10.61 --watch-poll

提示:本文图片等素材来源于网络,若有侵权,请发邮件至邮箱:[email protected]联系笔者删除。
笔者:苦海

你可能感兴趣的:(打包工具,webpack)