zoukankan      html  css  js  c++  java
  • webpack介绍与基础配置

      webpack是前端资源模块化管理和打包工具。它将很多单独,松散的模块按照一定的规则和依赖打包成符合生产环境部署的资源。它可以进行代码转换,文件优化,代码分割,模块合并,自动刷新,自动发布等多种功能。

      webpack中主要用到CommonJS和ES6Module。CommonJS定义的是模块的同步加载,它一般应用于服务器的开发,像node.js,而ES6Module,它是js官方标准模块定义的方式。webpack在代码解析的时候支持两种规范的解析。二者的导入和导出方式如下:

    /* ES6Module
     * 导出: export,export default(默认)
     * 导入: import
     */
    
    //文件名:a.js
    //代码如下:
    function sum(a, b) {
        return a + b
    }
    //使用export导出时要记得使用{}
    export { sum };
    //使用export default导出时,后面不用再加上{}
    export default sum
    
    //文件名:b.js
    //使用import导入时要记得变量名要写在{}中,要和导出一致,from后接的是相对路径
    import { sum } from './a';
    //可以在b.js中调用sum方法
    console.log(sum(1, 2));
    //导入,对应exprot default.import后面不用跟{},可以随意取变量名
    import A from './a';
    console.log(sum(3, 2));

      需要注意的是:模块的导入要放在代码的最前面,而且浏览器不能直接识别,需要先进行编译才可以。  

    /* 
     * CommonJS模块化
     *      导出:module.exports = {属性名:属性值}
     *      导入:let/const exports导出的对象名 = require('文件名')
     */ 
     //a.js
     function sum(x,y){
        return x+y
    }
    
    module.exports = {
        sum:sum,//简写sum
    }
    
    //b.js
    // 导入:
    let s = require('./a');
    console.log(s);

      webpack中一共有以下几个概念:

      入口(entry):它指示webpack应该使用哪个模块来作为构建其内部依赖图的开始。默认为:./src也可以通过配置entry中的属性来指定入口起点(一个或者多个)。。

      出口(output):它告诉webpack在哪时输出所创建的bundles,以及如名命名。默认为./dist。它也是可以配置多输口的。

      loader:模块转换,把模块原内容按照需求转换成新内容,可以加载非js的模块。本质上webpack loader将所有类型的文件转换为应用程序的依赖图可以引用的模块

      插件(plugins):扩展插件,在webpack构建流程中的特定时机注入扩展逻辑来改变构建的结果。它们都是可以进行配置的。想要使用一个插件,只需要用到require()它,然后把它添加到plugins数组中。多数插件是可以通过option来自定义选项的。

      模式(mode):通过development或production之中的任何一个来设置mode参数用以启用相应模式下webpack内置的优化。

      一、webpack的安装与基本使用

      目前我们一般采用的都是webpack4.0以上的版本,它支持零配置的使用。

      安装webpack,为了防止全局安装webpack导致的版本冲突,所以以本地安装为主。

      步骤一:新建一个文件夹,文件夹不能有特殊的字符。如:中文,特殊符号且名字不能是webpack否则会报错

      步骤二: 生成package.json文件。命令:npm init -y

      命令:npm i(install) webpack webpack-cli --save -dev   / npm i webpack webpack-cli -g

      步骤三:零配置使用。新建一个src文件夹,默认会打包src(当前项目开发的源代码)目录中的文件(入口默认为index.js),打包完成后的目录是dist/main.js编译后的文件。

      1、新建src目录且在src下分别创建a.js和index.js文件,代码如下:

    /* src/a.js */
    function sum(x,y){
        return x+y;
    }
    
    export {sum};
    
    /* src/index.js */
    
    import { sum } from './a.js'
    console.log(sum(1, 4));

      2、进行打包处理,由于npm没有安装在全局不能使用命令,所以有两种方法。一种是使用:npx webpack。第二种是修改package.json中的script配置。就可以用npm run server 命令了。如下:

    {
        "scripts":{
            "serve":"webpack"
        }
    }

      3、我们可以看到项目的目录如下:

       4、如果不能使用零配置,可以自己来进行配置,自定义基础配置。

        4.1 新建一个webpack.config.js或者是webpackfile.js的文件。由于webpack分为开发环境和生产环境,所以我们可以创建三个不同的config.js进行不同的配置。

        webpack.config.js中可以进行entry,output,mode等基础的配置。需要注意一点的是在output中编译后的文件名要加上hash值,用以保证每次生成的文件是不一样的,好清除强缓存。且输出的目录是一个绝对的路径,所以要用到node.js 中的path。

    const path = require('path');
     module.exports = {
         //设置编译的模式:development production(默认的)
         mode:'production',
         //设置编译的入口文件(真实项目中一般开发的代码都要放在src下)
         entry:'./src/main.js',
         //设置编译的出口文件
         output:{
             filename:'bundle.[hash:10].main.js',
             path:path.resolve(__dirname,'build')
         }
     }

      4.2  可以还新建两个不同的文件webpack.config.dev.js 和webpack.config.pro.js用来区分不同的环境所需要的不同内容。在package.confg.js中写两个环境都需要的内容。在package.json中进行配置。

      "scripts": {
        "serve":"webpack --config webpack.config.dev.js",
        "build":"webpack --config webpack.config.pro.js"
      },

       4.3  进行基本的自动化配置。

        利用html-webpack-plugin。这样每一次代码更改,复新编译过后,就不需要手动的去更改html中导入的js信息。命令:npm i html-webpack-plugin --save-dev进行下载;

        利用clean-webpack-plugin在每一次打包的时候都把之前打包的内容进行清空,即build下只保留最新的打包文件。命令:npm i clean-webpack-plugin --save-dev进行下载;

        利用webpack-dev-server可以创建一个web服务来自动监听代码的改变,自动编译,自动打开浏览器渲染页面。命令:npm i webpack-dev-server --save-dev进行下载。

       在配置html-webpack-plugin插件的时候需要注意的是路径的正确性,还有hash值是可以用来清除强缓存的,与output设置hash值是一样的,它也是可以进行配置。还可以把模板中的html代码进行压缩处理。

    const HtmlWebpackPlugin = require('html-webpack-plugin');
    const { CleanWebpackPlugin } = require('clean-webpack-plugin');
    module.exports = {
        plugins: [
            //配置指定的html模板
            new HtmlWebpackPlugin({
                //路径
                template: './public/index.html',
                //文件名
                filename: 'index.html',
                //设置hash值
                hash: true,
                //把模板中的html代码进行压缩
                minify: {
                    collapseWhitespace: true,
                    removeComments: true,
                    removeAttributeQuotes: true,
                    removeEmptyAttributes: true
                }
            }),
            //每一次打包把之前的都清空
            new CleanWebpackPlugin()
        ]
    }

      在配置dev-server时编译好的结果是放在计算机内存中并不会像之前那样编译出现在build下。需要注意的一点是要把webpack.json中script中的配置进行修改。

    // webpack.config.js
    module.exports = {
        devServer:{
            port:'8080',
            compress:true,
            contentBase:path.resolve(__dirname,"build"),
            open:true,
            hot:true
        }
    }
    // package.json
    "scripts": {
        "serve": "webpack-dev-server --open Chrome",
        "build": "webpack"
      }

      4.4  当我们有多入口,需要有多输口进行输出这样的需求时,这时,我们就要进行一系列的设置,配置多页面模板。

    const path = require('path');
    //配置多页面模板
    const htmlPlugins = ['index','login'].map(item=>{
        return new HtmlWebpackPlugin({
            template: `./public/${item}.html`,    
            filename: `${item}.html`,
            chunks:[item],//指定当前页面中的依赖项
            hash: true,
            minify: {
                collapseWhitespace: true,
                removeComments: true,
                removeAttributeQuotes: true,
                removeEmptyAttributes: true
            }
        });
    });
    module.exports = {
        //多入口 => key:value
        entry: {
            index:'./src/main.js',
            login:'./src/login.js'
        },
        output: {
            //[name]多入口中配置的属性名 index/login
            filename: '[name].[hash:10].min.js',
            //输出的目录(需要的是绝对路径)
            path: path.resolve(__dirname, 'build')
        },
        plugins: [
            //配置指定的html页面模板
            ...htmlPlugins,   
        ]
    }

      5.  webpack中的loader加载器。它可以用来处理css,less,图片,字体等等资源。

        5.1  处理css和less文件。使用之前必须先进行下载安装要用到style-loader、css-loader、less-style-loader,autoprefixer postcss-loader。命令:npm install css-loader style-loader less-loader autoprefixer postcss-loader --save -dev。

        style-loader把处理好的css以内嵌的方式插入到页面中;css-loader用来处理import这类语法,postcss-loader处理兼容性问题它需要和autoprefixer一起使用,在配置时,它还需要新建一个postcss.config.js的文件来添加配置,当然还需要在package.json中进配置。

        由于使用style-loader后css的引入是内嵌式的,这时就不是很方便,想要更好处理html中引入的css文件,还需要用到mini-css-extract-plugin来抽离css的内容。需要用到命令npm i mini-css-extract-plugin --save-dev进行下载和安装。

    const MiniCssExtractPlugin = require('mini-css-extract-plugin');
    //webpack.config.js中
    module.exports = {
        plugins: [
            //=>使用插件
            new MiniCssExtractPlugin({
                //=>设置编译后的文件名字
                filename: 'main.[hash:10].css'
            })
        ],
        // 配置loader
        module: {
            rules: [
                {
                    //基于正则来查看匹配哪些文件
                    test: /.(css|less)$/i,
                    use: [
                        // "style-loader",
                        // 如果要把css分离出来style-loader了,而写下面这一个loader 它替代了style方式
                        MiniCssExtractPlugin,
                        "css-loader",
                        "postcss-loader",
                        "less-loader",
    
                    ]
                }
            ]
        }
    }
    
    //package.json中浏览器的兼容配置
    "browserslist": [
        ">0.1%",
        "last 2 versiions"
    ]
    
    //新生成的postcss.config.js中
    module.exports = {
        plugins: [
            require('autoprefixer')
        ]
    }

      还可以使用optimize,uglifyjs或者是terser插件来优化压缩css和js文件,下面采用的是terser

      命令:npm install optimize-css-assets-webpack-plugin terser-webpack-plugin --save -dev

      配置:

    const TerserWebpackPlugin  = require('terser-webpack-plugin');
    const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
    module.exports = {
        //配置webpack优化项
        optimization:{
            //设置压缩方式
            minimizer:[
                new OptimizeCssAssetsWebpackPlugin(),
                new TerserWebpackPlugin()
            ] 
        }
    }

      5.2  处理图片,字体文件

      在真实的项目中图片应用的位置在三处:css中的背景图,js中动态创建图片,html中直接写入图片

      命令:npm install file-loader url-loader html-withimg-loader --save-dev

    module.exports = {
        module: {
            //=>模块规则:使用加载器(默认从右向左执行)
            rules: [{
                test: /.(png|jpe?g|gif)$/i,
                use: [{
                    //=>把指定大小内的图片BASE64
                    //=>不在指定范围的采用file-loader进行处理
                    loader: 'url-loader',
                    options: {
                        limit: 200 * 1024,
                        outputPath:'/images',
                        //name:'[name].[ext]'
                    }
                }],
                include: path.resolve(__dirname, 'src'),
                exclude: /node_modules/
            }, {
               test:/.(svg|eot|ttf|woff|woff2)$/i,
               use:"file-loader"
            }, {
                test: /.html$/,
                use: ['html-withimg-loader']
            }]
        }
    }

     5.3 基于babel实现es6的转换和esList语法检测

      安装包依赖

      命令:$ npm install babel-loader @babel/core @babel/preset-env  –save-dev

      对于现在的开发来说,还有更高级的js语法如es7,8需要进行转换,所以还需要另外包的依赖和插件配置。一般要用到以下插件,先进行下载

      命令:$ npm install @babel/plugin-proposal-class-properties @babel/plugin-proposal-decorators @babel/plugin-transform-runtime –save-dev 

      在真实的目中我们还会安装@babel/polyfill来进行兼容的处理。它和其它的webpack加载器插件不一样,其它是编译时进行处理,而polyfill是运行时处理。 在代码运行时,把一些es7等特殊语法进行兼容处理,它需要安装在生产环境下。也需要@babel/plugin-transform-runtime插件的支持。在真实的项目中我们还会安装一个ESLint 来进行词法解析。

      命令:npm i @babel/runtime @babel/polyfill   npm i eslint eslint-loader -save-dev

      综上配置如下:

    module.exports = {
        module: {
            rules: [{
                test: /.js$/,
                use: [{
                    loader: 'babel-loader',
                    options: {
                        //=>转换的语法预设(ES6->ES5)
                        presets: [
                            "@babel/preset-env"
                        ],
                        //=>基于插件处理ES6/ES7中CLASS的特殊语法
                        plugins: [
                            ["@babel/plugin-proposal-decorators", {
                                "legacy": true
                            }],
                            ["@babel/plugin-proposal-class-properties", {
                                "loose": true
                            }],
                            "@babel/plugin-transform-runtime"
                        ]
                    }
                }], //=>, "eslint-loader"
                //=>设置编译时忽略的文件和指定编译目录
                include: path.resolve(__dirname, 'src'),
                exclude: /node_modules/
            }]
        }
    }

     

      

      

         

     

     

      

      

     

  • 相关阅读:
    验证foreach 能否操做更改原表
    asp.net post/get 公共方法
    C# json日期转换
    学数学
    2742: [HEOI2012]Akai的数学作业
    BZOJ2208
    树状数组求逆序对
    网络流复习计划
    SG函数学(hua)习(shui)记录
    SPLAY板子
  • 原文地址:https://www.cnblogs.com/davina123/p/13298874.html
Copyright © 2011-2022 走看看