模块化开发与规范化标准

概述

1.模块化演变过程
2.模块化规范
3.常用的模块化打包工具
4.基于模块化工具构建现代web应用
5.打包工具的优化技巧

模块化演变过程

1.污染全局作用域
2.命名冲突问题
3.无法管理模块依赖关系

模块化规范的出现

1.CommonJS
一个文件就是一个模块
每个模块都有单独的作用域
通过module.exports导出成员
通过require函数载入模块
是以同步模式加载模块(在浏览器中 加载缓慢)
2.AMD(Asynchronous Module Definition) Require.js

ES Modules 特性

1.CommonJS
一个文件就是一个模块
每个模块都有单独的作用域
通过module.exports导出成员
通过require函数载入模块
是以同步模式加载模块(在浏览器中 加载缓慢)
2.AMD(Asynchronous Module Definition) Require.js

ES Modules 特性

1.自动采用严格模式,忽略’use strict’
2.每个ESM模块都是单独的私有作用域
3.ESM是通过cors去请求外部JS模块的(外模模块需要支持跨域)
4.ESM的script标签会延迟执行脚本(异步)

ES Modules 导出和导入

  export { foo } 导出一个成员引用 不是一个对象
  import { foo } from './*.js' 导入

  export default foo 默认导出 可以导出一个对象
  import abc from './*.js'  导入变量名可以变化

babel 兼容性方案

yarn add @babel/node @babel/core @babel/preset-env --dev
babel模块依赖一些核心模块 基于插件形式实现的
@babel/preset-env 是一个插件的集合 一个插件实现一个功能转换
yarn babel-node index.js --presets=@babel/preset-env
@babel/preset-env可以放在.babelrc配置 {"presets":["@babel/preset-env"]}
yarn babel-node index.js

一.Webpack 的构建流程主要有哪些环节?如果可以请尽可能详尽的描述 Webpack 打包的整个过程。

环节

1.初始化项目 安装webpack
2.配置文件webpack.config.js
3.配置项目入口(entry)、输出路径(output)、开发模式(mode)等
4.根据要加载的文件类型,安装配置不同的loader加载器
5.实现非loader的功能,安装相应的plugins
6.配置devserver 开启自动化编译和浏览器预览
7.配置optimization 进行项目优化操作

打包过程

1.执行打包命令(webpack)
2.通过webpack.config.js配置文件的entry入口配置开始查找项目依赖资源
3.根据配置的loader解析不同的资源,输出打包后的资源
4.在webpack打包过程中根据不同的环境配置不同plugin做一些额外的工作和一些优化操作
5.最后(output)输出Chunk文件 可多个或静态不变

plugin:主要是在webpack构建的不同阶段执行一些额外的工作,比如拷贝静态资源、清空打包后的文件夹等

1.通过钩子机制实现
2.plugin必须是一个函数或包含apply方法的对象
3.在方法体内通过webpack提供的API获取资源做响应处理
4.将处理完的资源通过webpack提供的方法返回该资源

class MyPlugin{
  // 传入相应的配置信息
  constructor(options){
  }

  // 将Compiler对象传递进来
  // 然后通过这个对象来注册钩子函数
  apply(compiler){
      // 注册emit钩子方法
      // compilation是一个上下文,
      compiler.hooks.emit.tap("MyPlugin",compilation=>{
          //在这里执行我们的方法来修改内容
        })
    }
}

二.webpack配置vue开发的流程

1.首先我们需要安装webpack webpack-cli到我们的开发依赖中

一阶段:在module.common.js文件 配置项目入口(entry)、输出路径(output)

二阶段:

    1.根据要加载的文件类型,安装配置不同的loader加载器
      因为我们项目是vue 所以我们需要安装vue-loader的依赖来对vue文件进行解析和转换
    2.接下来,由于我们项目中使用的是less,所以我们需要安装less-loader来对less进行解析和编译,同时,我们还需要安装css-loader和style-loader来对css文件和vue中的style标签进行解析
    注意:如果use是多个 顺序是从后到前执行 css解析需要style、css loader一起使用
    3.接下来是对js文件的解析,这里我们需要使用到babel-loader,将ES6+转为ES5
    注意:babel-loader内部会调用@babel/core 进行语法转换,@babel/core的转换依赖预设@babel/preset-env
    4.再然后是对图片文件的处理,我们使用url-loader来处理。由于url-loader是基于file-loader的

三阶段:

    1.因为是vue项目,需要使用一个VueLoaderPlugin插件引入
    2.此时我们发现没有html的解析文件,如果所以我们需要安装一个htm-webpack-plugin,用于指定html模板来生成我们的index.html,还可以设置title、meta等
      由于过程BASE_URL会报错所以我们需要使用webpack的DefinePlugin来定义一下BASE_URL的位置

四阶段:分配不同环境 通过webpack-merge 合并其他配置 类似Object.assign()

   1.开发环境的配置
     (1)mode模式分为三种 分别是 production、development 和 none 开发选择development
     (2)指定sourceMap 开发中方便找到源码中错误的位置
     (3)开发环境需要配置eslint 在保存时检查代码规范
     (4)配置devServer 启动热更新 提高开发效率 或使用代理服务 解决跨域
   1.生产环境的配置  
     (1)mode选择production
     (2)去除sourceMap 防止源码暴露
     (3)我们所有的代码都打包到了一个js文件中,接下来,我们首先把css样式文件分离出来,这一步我们需要使用到mini-css-extract-plugin,并且我们需要更改一下less和css文件的loader
     (4)我们需要做的就是对css文件和js文件的压缩和分包,并且通过webpack来去掉代码中的dubugger,console等,这一步我们需要使用optimize-css-assets-webpack-plugin 和 terser-webpack-plugin

最后:由于命令行的长度太长了,所以我们可以吧命令直接使用npm script的方式来执行,具体就是修改package.json里面的东西

webpack.common.js 代码演示

const path = require("path")
const VueLoaderPlugin = require("vue-loader/lib/plugin")
const HtmlWebpackPlugin = require("html-webpack-plugin")

// 公共的打包配置
module.exports = {
    // 入口文件 可以多个入口
    // entry: {
    //     index: './src/index.js',
    //     album: './src/album.js'
    // },
    entry: "./src/main.js",
    // 输出文件
    output: {
        // __dirname生成绝对路径
        path: path.resolve(__dirname, "dist")
    },
    module: {
        rules: [
            {
                // 解析vue文件
                test: /\.vue$/,
                use: ["vue-loader"]
            },
            {
                // 对js进行代码转译
                test: /\.js$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        // babel-loader内部会调用@babel/core 进行语法转换,@babel/core的转换依赖预设@babel/preset-env和插件plugin 
                        presets: ['@babel/preset-env']
                    }
                }
            },
            {
                // 对图片文件的处理 由于url-loader 是基于file-loader的,所以我们需要同时安装这个依赖
                test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
                use: {
                    loader: "url-loader",
                    // 限制图片大小 超过10k文件存储,不超过转base64
                    options: {
                        limit: 10 * 1024,
                        // 不加 src中会是一个object module
                        esModule: false
                    }
                }
            }
        ]
    },
    plugins: [
        new VueLoaderPlugin(),
        // 用于生成 index.html 多个HtmlWebpackPlugin可以生成不同*.html
        new HtmlWebpackPlugin({
            title: 'Webpack Plugin Sample',
            meta: {
                viewport: 'width=device-width'
            },
            template: "./public/index.html"
            // filename: 'index.html', //指定生成文件名
            // chunks: ['index']
        })
    ],

}

webpack.dev.js 代码演示

const { merge } = require("webpack-merge") //合并其他配置 类似Object.assign()
const commonConfig = require("./webpack.common")
const { DefinePlugin } = require("webpack")

// 开发环境的配置
module.exports = merge(commonConfig, {
    // 这个属性有三种取值,分别是 production、development 和 none。
    // 1. 生产模式下,Webpack 会自动优化打包结果;
    // 2. 开发模式下,Webpack 会自动优化打包速度,添加一些调试过程中的辅助;
    // 3. None 模式下,Webpack 就是运行最原始的打包,不做任何额外处理;
    mode: 'development',
    //指定sourceMap 开发中方便找到源码中错误的位置
    devtool: "#@cheap-module-source-map",
    module: {
        rules: [
            {

                test: /\.(vue|js)$/,
                loader: "eslint-loader",
                exclude: /node_modules/,
                // 预处理
                enforce: "pre"
            },
            {
                //如果use是多个 顺序是从后到前执行 css解析需要style、css loader一起使用
                test: /\.less$/,
                use: ["style-loader", "css-loader", "less-loader"]
            },
            {
                //这个是用来转换vue中的style标签和css文件的
                test: /\.css$/,
                use: ["style-loader", "css-loader"]
            },
        ]
    },
    devServer: {
        contentBase: './public', //指定服务器资源的根目录
        proxy: { //代理 本地解决跨域问题
            '/api': {
                // http://localhost:8080/api/users -> https://api.github.com/api/users
                target: 'https://api.github.com',
                // http://localhost:8080/api/users -> https://api.github.com/users
                pathRewrite: {
                    '^/api': ''
                },
                // 不能使用 localhost:8080 作为请求 GitHub 的主机名
                changeOrigin: true
            }
        },
        port: 9000,
        open: true,  //执行命令时自动打开页面
        hot: true //每次更新资源文件,不用更新所有资源,只更新部分,相当于加了一个补丁
    },
    plugins: [
        new DefinePlugin({
            //定义BASE_URL index.html中需要使用
            BASE_URL: "/public/"
        })
    ]
})

webpack.prod.js 代码演示

const { merge } = require("webpack-merge");
const commonConfig = require("./webpack.common");
const { DefinePlugin, LoaderOptionsPlugin } = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); //webpack4.X
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); 
const TerserPlugin = require("terser-webpack-plugin");
const path = require("path");

//生产环境的配置
module.exports = merge(commonConfig, {
    mode: "production",
    //去除sourceMap 防止源码暴露
    devtool: "none",

    //输出的文件名
    output: {
        filename: "js/[name].[hash:8].js",
        publicPath: "./"
    },
    //更改css和less的loader
    module: {
        rules: [
            {
                test: /\.less$/,
                use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"]
            },
            {
                test: /\.css$/,
                use: [MiniCssExtractPlugin.loader, "css-loader"]
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: "./public/index.html",
            favicon: "./public/favicon.ico", // 在此处设置
            //对html代码进行压缩
            minify: {
                removeComments: true, //去注释
                collapseWhitespace: true, //压缩空格
                removeAttributeQuotes: true //去除属性引用
            }
        }),
        new DefinePlugin({
            BASE_URL: process.env.NODE_ENV
        }),
        //用于每次生成的时候,清理上次的打包文件
        new CleanWebpackPlugin(),
        //主要是为了抽离 css 样式,防止将样式打包在 js 中文件过大和因为文件大网络请求超时的情况 
        new MiniCssExtractPlugin({
            // hash/chunkhash解决缓存
            filename: "css/[name].[hash:7].css",
            chunkname: path.posix.join("static", "css/[id].[chunkhash:7].css")
        })
    ],
    optimization: {
        //代码分包 自动提取所有公共模块到单独包
        splitChunks: {
            chunks: "all"
        },
        minimize: true,
        minimizer: [
            //css压缩
            new OptimizeCSSAssetsPlugin({
                cssProcessorOptions: {
                    discardComments: { remove: true } //移除注释
                }
            }),
            //js优化
            new TerserPlugin({
                parallel: true, //开启多线程来提高构建速度
                sourceMap: false,
                terserOptions: {
                    warnings: false, //不展示warning
                    compress: {
                        unused: true, //去除未使用的
                        drop_debugger: true, //移除debugger
                        drop_console: true //去除console
                    },
                    output: {
                        comments: false //去除注释
                    }
                }
            })
        ]
    }
})

package.json

  "scripts": {
    "serve": "npx webpack-dev-server --config webpack.dev.js",
    "build": "webpack --config webpack.prod.js",
    "lint": "eslint ./src"
  },

webpack 加载资源的方式

1.遵循 ES Modules 标准的 import 声明
2.遵循 CommonJS 标准的 require 函数
3.遵循 AMD 标准的 define 函数和 require 函数
4.样式代码中的 @import 执行和 url 函数
5.HTML 代码中图片标签的 src 属性

Webpack 代码分割

代码分包

所有代码最终都被打包到一起,bundle 体积过大
并不是每个模块在启动时都是必要的
模块打包是必要的,但是应用越来越大之后,需要进行分包,按需加载
有两种方式:多入口打包;ESM 动态导入

多入口打包

常用于多页应用程序
一个页面对应一个打包入口
公共部分单独提取

动态导入

按需加载,需要用到某个模块时,再加载这个模块
可以极大地节省带宽和流量
无需配置任何地方,只需要按照 ESM 动态导入的方式去导入模块,webpack 内部会自动处理分包和按需加载
使用单页应用开发框架(React/Vue),在项目中的路由映射组件就可以通过动态导入实现按需加载

Webpack 魔法注释

使用魔法注释可以为动态导入最终打包出来的文件命名
命名相同的模块最终会被打包到一起

Webpack 输出文件名 Hash

一般我们部署前端资源文件时,都会采用服务器的静态资源缓存
开启缓存的问题:缓存时间过短-效果不明显,缓存过期时间较长-应用发生了更新重新部署后客户端因为缓存得不到更新
解决上面问题,建议生产模式下,文件名使用 Hash,文件名不同也就是新的请求,解决了缓存的问题,服务器可以将缓存过期时间设置足够长

三种 Hash 方式

hash: 整个项目级别的,项目中任意一个地方改动,重新打包之后的 hash 值都会改变
chunkhash: chunk 级别的,同一路的打包 chunkhash 都是相同的
contenthash: 文件级别的hash,根据文件内容生成的hash值,不同的文件就有不同的值
解决缓存问题的最佳 hash 方式 [contenthash:8]

原文地址:https://blog.csdn.net/weixin_52026514/article/details/112200651

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


一准备工作umi为react的一个封装比较nice的脚手架。优点当然就是安装方便,开箱即用,集成了诸多好用功能,详见官网。当然缺点就是无法暴露原始的webpack.config.json文件,只能按照官方文档上特定的方法进行修改,而文档却并不完善。项目顺利进行大家笑嘻嘻,一旦遇到偏难怪需求,
webpack在引入两个依赖的包时,可能需要使用shimming,意思是处理代码上的兼容1、在main.js中引入jqueryimport$from'jquery'importappendfrom'./append'//下面的给页面添加元素文件append()2、append.js使用main.js的$向页面中添加元素functionappDomFunc(){
  Happypack (plugin)多线程使用loader编译文件treeshaking删除无用JS代码,依赖ESM规范source-map生产环境一定去掉process.env.XXX配置环境变量,区分各种编译环境splitchunks 代码分离去重DynamicImport动态加载js文件Hot-module-replacement开发环境热更新w
一目录结构├──build//构建相关├──config//配置相关├──src//源代码│├──api//所有请求│├──assets//主题字体等静态资源│
接着第一节的demo现在我们尝试整合一些其他资源,比如图像,看看webpack如何处理。在webpack出现之前,前端开发人员会使用grunt和gulp等工具来处理资源,并将它们从 /src 文件夹移动到 /dist 或 /build 目录中。同样方式也被用于JavaScript模块,但是,像webpack这样的工
webpack的打包原理识别入口文件通过逐层识别模块依赖(Commonjs、amd或者es6的import,webpack都会对其进行分析,来获取代码的依赖)webpack做的就是分析代码,转换代码,编译代码,输出代码最终形成打包后的代码什么是loaderloader是文件加载器,能够加载资源文件,并对这些文件进行
上一篇文章我们在一个demo中见到了webpack的身影,如果从未接触过webpack的同学学完了上一篇文章可能会觉得webpack只是一个“翻译官”,但事实上webpack可不仅仅可以‘翻译’代码,事实上,webpack是一个‘打包’工具,‘打包‘才是webpack的核心任务。打开webpack的官网:webpack中
注:本章将配合Vue详细讲解webpack前提条件1.在开始之前,请确保安装了Node.js和npm的最新版本。使用旧版本,你可能遇到各种问题,因为它们可能缺少webpack功能以及/或者缺少相关package包。在cmd中node-v,npm-v可查看对应的版本和安装情况。2.这里会用到ES6的模块化,如果你
前言、之前我认为对于项目的优化无非是从代码上去优化一些东西,比如循环呀函数式调用呀让你的代码看起来更加的简洁容易懂后来我在面试过程中不断有面试官不断地问了我这些问题所以自己就去研究了一下发现并不是我之前想的那样,一个好的webapck优化的胜过于你在整体代码上
##一、组件component###1.什么是组件?组件(Component)是Vue.js最强大的功能之一。组件可以扩展HTML元素,封装可重用的代码组件是自定义元素(对象)###2.定义组件的方式方式1:先创建组件构造器,然后由组件构造器创建组件方式2:直接创建组件###3.组件的分
 #webpack5概述>webpack是一个现代javascript应用程序的**静态模块打包器(modulebundler)**>>vue-cli脚手架环境,集成了webpack,所以才能对各类文件进行打包处理[webpack官网](https://webpack.js.org/) ##webpack能做什么webpack是一个静态模块打包
//这里导入webpack配置,我用对象的形式表示,当然entry属性上定义的文件要有//constconfig=require("./webpack.config");constconfig={entry:'./src/index.js'};const{join,dirname}=require("path");const{readFileSync,writeFileSync}=requi
安装cnpminstallwebpack-bundle-analyzer-D 修改vue.config.jsmodule.exports={chainWebpack:config=>{if(process.env.use_analyzer){//分析config.plugin('webpack-bundle-analyzer')
webpack打包html插件html-webpack-plugin的使用1.创建这样的测试目录结构1)index.html是即将被打包的文件,你可以随便写一些内容2)index.js是打包的入口文件,你可以写或不写内容2.webpack.config.js的代码如下:/***压缩html需要插件:html-webpack=plugin*插件使用方法:
vueinitwebpacktabbar创建vue项目时出现问题vue:无法加载文件C:\Users\dengqian\AppData\Roaming\npm\vue.ps1,因为在此系统上禁止运行脚本。C:\Windows\System32\WindowsPowerShell\v1.0,找到如上路径,以管理员身份运行powershell.exe即可输入set-ExecutionPolicyRemo
在webpack中使用ECharts【官网教程】1、使用如下命令通过npm 安装EChartsnpminstallecharts--save2、全局引用在main.jsimportechartsfrom'echarts'Vue.prototype.$echarts=echarts;3、运用<divstyle="width:60vw;height:280px;"ref="chart"&
如果没有看过我的上一篇文章,请先移步去看一下哈!时隔一年多,之前写的文章感觉大家还挺喜欢的,一直说要更新下一篇。但是一直没有机会,没时间,还有就是,感觉自己的技术,可能不足以支持我继续往下走。但是经过这个一年多的历练,感觉很多东西考虑的会更周全,不负期待!废话说一堆,步入正题
dist文件配置对应的路由名展示这样的效果可以创建一个本地的服务还可以进行代理项目开发是在src里进行代码逻辑编写./表示本地路径/表示绝对路径(nginx需要配置)
 1、用命令创建webpack模板项目vueinitwebpack 项目名,需要选是否的统一选否,所以的依赖手动添加  2、安装依赖vue-router,elementui,sass-loader,node-sass,axios插件安装路由:npminstallvue-router安装elementu
最近想把蘑菇博客部署到k8s上,作为一名java搬砖工,搬砖人不讲码德,biu一下就把后端各模块的dockerfile和chart包copy过来了,很快啊!接下来就可以愉快的使用helm管理蘑菇后端服务部署了。部署完后端服务后,准备制作前端镜像,发现前端打包后,无法动态读取系统环境变量,这很头疼,难不