一、webpack安装

webpack官方文档:https://www.webpackjs.com/

npm官方文档:https://www.npmjs.cn/

    webpack可以全局安装-g或者局部安装-D 命令:npm i webpack webpack-cli -D

    webpack可以0配置打包,npx webpack,原理就是在node_modules下的bin目录中找到对应的命令执行,但是有局限,只能指定文件下的index.js文件才可以打包,在项目中我们不推荐0配置打包。

    webpack不是用于单个文件打包的,主要功能是进行多文件打包。

二、webpack项目配置

       配置有四大核心概念:

              入口(entry)

              输出(output)

              loader

              插件(plugins)

      在根目录下创建webpack.config.js文件,webpack配置遵循CommonJS规范,使用module.exports进行暴露、属性entry路径可以设置相对路径,output属性设置的path路径必须是绝对定位,我们可以引用path插件进行设置,

output:{path.resolve()  //解析当前相对路径为绝对路径path.join(__dirname)  //拼接路径  __dirname找到当前文件的根目录进行拼接filename:''  //打包之后输出在path文件夹下的文件
}

如果不设置打包环境,默认打包环境是product(上线环境),可以使用mode进行生产环境和上线环境设置

mode:"development"    //默认是product

三、webpack自动编译功能

       三种模式可以进行自动编译

           1、webpack Watch Mode  监视文件是否有变化,使用 --watch  或者在webpack.confg.js文件中加上watch:true开启监视

           2、webpack -dev-server

          3.、webpack-dev-middleware

我们在项目中用到的最多的就是2方法,我们也就只学2方法

           webpack -dev-server是一个插件,需要安装,在package.json中设置,webpack -dev-server打包的js文件是存在内存中的,不存在我们的硬盘中,我们看不到,在package.json中设置

'dev':"webpack-dev-server --open --hot --port 3000 --contentBase src --compress"// open 编译自动打开默认浏览器
// hot 热加载,只编译修改的部分
// port 设置端口号
// contentBase 设置根目录
// compress 压缩,在服务端的强制压缩

我们也可以在webpack.config.js文件中设置,

devServer:{open:true,hot:true,   //开启热更新compress:true,port:3000,contentBase:'/src'
}

到了这里我们需要用到一个很牛逼的插件 html-webpack-plugin,安装 npm i html-webpack-plugin -D,在webpack.config.js中引用,html-webpack-plugin作用是自动在根目录帮我们根据模板生成一个index.html,它也是存在于内存中,不存在硬盘中,我们也是看不到的,另一个作用是自动帮我们引入打包生成的js文件,不需要我们在手动修改。

在webpack.config.js中设置

plugins:[new HtmlWebpackPlugin({filename:打包之后生成的html的名字,template:根据某个模板生成上面打包的模板,此处写模板的路径位置})
]

打包时自动生成index.html文件

     loader的使用,处理css,sass,scss es6高级语言,图片,为甚么使用loader,因为在main.js中引用css等文件,js无法解析,此时就需要一个加载器进行帮助js去解析

处理css的loader:安装npm i css-loader style-loader -D

处理less和sass的loader:安装npm i less less-loader sass-loader node-sass -D

处理图片和字体的loader:安装 npm i file-loader url-loader -D   url-loader是对file-loafer的封装,可以对图片进行大小限制

在webpack.config.js中配置

module:{rules:[// loader的调用是从右向左管道的方式链式调用// css-loader的作用:解析后缀名是css结尾的文件// style-loader作用:将解析之后的文件放入html之中{test:/\.css$/,use:['style-loader','css-loader']},{test:/\.s(a|c)ss$/,use:['style-loader','css-loader','sass-loader']},{test:/\.(png|jpg|gif|woff|svg)$/,use:{loader:'url-loader',options:{limit:2*1024  //大于2kb时显示图片路径,小于2kb时转换为base64}}},{test:/\.(woff|svg|woff2|ttf|eot)$/,use:'file-loader'}]
}

图片打包之后会都存在dist文件中,而且名字还是hash值,特别长,此时我们可以进行设置

module:{rules:[{test:/\.(png|jpg|gif|woff|svg)$/,use:{loader:'url-loader',options:{limit:2*1024,  //大于2kb时显示图片路径,小于2kb时转换为base64outputPath:'image',//打包之后生成的图片都放在image文件夹中name:'[name]-[hash:7].[ext]'  //[name]保留原图片的名称,[hash:7]随机生成的hash值保留前7位值,[ext]保留原图片的后缀值}}}]
}

处理js中es6高级语法babel-loader:安装 npm i babel-loader @babel/core @babel/preset-env webpack -D

npm i @babel/plugin-proposal-class-properties -D 为了处理兼容更高级的语法

module:{rules:[{test:/\.js$/,use:{loader:'babel-loader',options:{presets:['@babel/env'],plugins:['@babel/plugin-proposal-class-properties'] }}}]
}

babel中都是预要发布的新语法,想要在项目中用到什么新的语法,可以到babel中下载使用。然后在plugin中引用。

我们在打包的时候有时候需要排除一些不需要打包的js文件,我们只需要打包自己写的js代码,此时我们就需要用到exclude

module:{rules:[{test:/\.js$/,use:{loader:'babel-loader',options:{presets:['@babel/env'],plugins:['@babel/plugin-proposal-class-properties'] }},exclude:/node_modules/   //不需要打包的js文件include:/index.js/  //包含需要打包的js文件}]
}

处理js文件中generator语法转换,

generator的解释:

Generator函数时ES6提供的一种异步编程解决方案。Generator语法行为和普通函数完全不同,我们可以把Generator理解为一个包含了多个内部状态的状态机

执行Generator函数回返回一个遍历器对象,也就是说Generator函数除了提供状态机,还可以生成遍历器对象。Generator可以此返回多个遍历器对象,通过这个对象可以访问到Generator函数内部的多个状态。

形式上Generator函数和普通的函数有两点不同,一是function关键字后面函数名前面有一个星花符号“*”,二是,函数体内部使用yield定义(生产)不同的内部状态

执行Generator函数返回的是一个遍历器对象,这个对象上有一个next方法,执行next方法会返回一个对象,这个对象上有两个属性,一个是value,是yield关键字后面的表达式的值,一个是done布尔类型true表示没有遇到return语句,可以继续往下执行,false表示遇到return语句。代码示例如下:

function* helloWorldGenerator () {yield 'hello';yield 'world';return 'ending';}var hw = helloWorldGenerator();console.log(hw.next()); //第一次调用,Generator函数开始执行,直到遇到yield表达式为止。next方法返回一个对象,它的value属性就是当前yield语句后面表达式的值hello,done属性为false,表示遍历还没有结束console.log(hw.next()); //第二次调用,Generator函数从上次yield表达式停下的地方,一直执行到下一个yield表达式。next方法返回的对象的value属性就是当前yield语句后面表达式的值world,done属性值为false,表示遍历还没有结束。console.log(hw.next()); //第三次调用,Generator函数从上次yield表达式停下的地方,一直执行到return语句(如果没有return语句,则value属性为undefined),done属性为true,表示遍历已经执行结束。console.log(hw.next()); //第四次调用,此时Generator函数已经执行完毕,next方法返回对戏那个的value属性为undefined,done属性为true,表示遍历结束。console.log(hw.next()); //第五次执行和第四次执行的结果是一样的。

执行结果:

1. 定义Generator函数helloWorldGenerator函数
2. 函数内部有2个yield表达式和一个return语句,return语句结束执行
3. Generator函数的调用方法和普通函数一样,也是在函数名后面加上一对圆括号。不同的是调用之后,函数不是立即执行,返回的也不是return语句的结果undefined,而是一个指向内部状态的指针对象,也就是上面说的遍历器对象(Iterator Object)
4. 调用遍历器对象的next方法,状态指针移动到下一个状态,返回{value: "hello", done: false}
5. 调用遍历器对象的next方法,状态指针移动到下一个状态,返回{value: "world", done: false}
6. 调用遍历器对象的next方法,状态指针移动到下一个状态,返回{value: "ending", done: true},done为true,说明已经遇到了return语句,后面已经没有状态可以返回了
7. 调用遍历器对象的next方法,指针不再移动,返回{value: undefined, done: true}
8. 调用遍历器对象的next方法,指针不再移动,返回{value: undefined, done: true}

注意yield表达式后面的表达式,只有当调用next方法,内部指针指向该语句时才会执行,相当于JavaScript提供了手动的“惰性求值”语法功能。

如果要在低版本的浏览器中使用generator语法,此时我们就要用babel去处理,安装 npm install -D @babel/plugin-transform-runtime  和  npm install -save @babel/runtime

module:{rules:[{test:/\.js$/,use:{loader:'babel-loader',options:{presets:['@babel/env'],plugins:['@babel/plugin-proposal-class-properties','@babel/plugin-transform-runtime'] }}}]
}

为了便于开发维护,我们一般把插件配置单独写在根目录下的 .babelrc文件下,格式是json,代码如下:

{"presets":["@babel/env"],"plugins":["@babel/plugin-proposal-class-properties","@babel/plugin-transform-runtime"] 
}

高版本的原型方法的转义@babel/polyfill    使用polyfill进行新的api进行转换 babel是对JavaScript的新的语法转换

安装npm install @babel/polyfill,该模块需要在使用新方法的地方引用(在main.js中引用)(即打补丁)

import 'babel-polyfill'

source map的使用,快速解决定位在浏览器中代码打印||报错位置,便于我们快速开发,

source map有很多模式,此时我们建议使用带cheap的eval的品质是原始代码的模式,推荐使用cheap-module-eval-source-map

在webpack.config.js文件中设置代码如下:

devtool:'cheap-module-eval-source-map'

每次打包之前都需要把之前打包的dist文件删除插件:安装 npm install clean-webpack-plugin -D,使用插件,引入,直接在plugin中创建对象即可,代码如下:

plugins:[new CleanWebpackPlugin({})
]

静态资源都是不参与打包的,但是为了打包之后让静态资源进入到dist的文件夹列表中,我们需要用到插件 copy-webpack-plugin

此时我们一般把静态文件都放在assets文件夹中,插件安装:npm i copy-webpack-plugin -D,引入插件,设置插件

plugins:[new CopyWebpackPlugin({from:path.join(__dirname,'assets'),to:''assets})
]

除了第三方的webpack插件,webpack还有自己的内置插件,

BannerPlugin 就是webpack的内置插件,他的作用就是给打包过的文件添加版权注释信息,因为是内置的,不需要安装,直接引用,首先要先引用webpack,const webpack =requirr('webpack')代码实现:

plugins:[new webpack.BannerPlugin('三和大神')
]

在html中引用的图片资源,build之后不会被打包,要使用我们上面学习到的loader(copy-webpack-plugin),但是前提这个图片是被放在assets文件夹下的,但是不是所有的img图片文件都是放在assets文件夹下的,有的图片资源是放在src文件下的,如果在html中直接引用,是不会被打包进dist中,此时我们就需要loader插件(html-withing-loader),安装loader:npm i -S html-withing-loader,loader安装之后,我们在html中引用图片使用正常的路径就可以,也可以进行打包

在webpack.config.js中配置,代码如下:

module:{rules:[{test:/\.(htm|html)$/i,loader:'html-withing-loader'}]
}

   多页应用打包

当有多个js文件入口的时候,我们就要有对应的多个html文件进行引用,此时我们就需要对webpack.config.js配置进行修改,

module.exports={// 1、修改为多入口entry:{index:'index.js',other:'other.js'},output:{path:path.join(__dirname,'./dist'),// 2、修改多入口对应的出口为变量filename:'[name].js',publicPath:'/'},plugin:[// 3、如果用了html插件,需要手动设置多入口对应的html文件,将指定其对应的输出文件new HtmlWebpackPlugin({filename:'index.html',template:'./index.html',chunks:['index']   //找到对应的生成js,然后引用}),new HtmlWebpackPlugin({filename:'other.html',template:'./other.html',chunks:['other']   //找到对应的生成js,然后引用到生成的html文件中})]
}

第三方库的两种引用方式

expose-loader 作用将库引入到全局作用域

安装 npm i -D expose-loader

配置loader

module:{rules:[//require.resolve 用来获取模块的绝对路径,所以这里的loader只会作用到jQuery,并且只会在打包中使用到他时,才会进行处理{test:require.resolve('jquery'),use:{loader:'expose-loader',options:'$'}}]
}

webpack-ProvidePlugin 是webpack内置插件,作用将库自动加载到每个模块

直接在webpack.config.js中配置,代码如下:

plugins:[new webpack.ProvidePlugin({$:'jquery',jQuery:'jquery'})
]

Development / production 不同配置文件打包

项目开发一般需要开发环境和生产环境,用于开发环境的阶段(不压缩代码,不优化代码,增加效率),生产环境的阶段(压缩代码,优化代码,打包后直接上线使用),此时我们就需要抽取三个配置文件:

webpack.base.js      webpack.prod.js     webpack.dev.js

实现步骤如下:

1、将开发环境和生产环境公用的配置放在base中,不同的配置各自放入prod或dev中,(有针对的进行删除)

2、然后在dev和prof中使用webpack-merge把配置与base的配置进行合并后导出

    2.1 安装webpack-merge -D,在dev和prod中引用webpack-merge,

    2.2 在dev和prod中引入base文件

    2.3 在dev和prod中进行配置

// webpack遵循的是nodeJs的commonJS规范
const merge = require('/webpack-merge')
const webpackBase =require('/webpack.base.js')const webpackProd=merge(webpackBase ,{// webpack.prod.js或者webPack.dev.js保留的配置文件
})module.exports=webpackProd

3、将package.json中的脚本参数进行修改,通过--config手动指定特定的配置文件

"scripts":{"build":"webpack --config /webpack.prod.js","server":"webpack --config /webpack.dev.js
}

webpack配置文件分类

我们将webpack.base.js   webpack.prod.js webpack.dev.js 都放在根目录显然不是很友好,此时我们在根目录下新建一个文件夹build。将上述三个文件都移动到build中,但是移动文件之后package.json中的启动路径需要进行相应的修改,webpack.base,js中使用path拼接的绝对定位也需要进行相应的修改,否则会进行报错,打包之后dist文件会存放到build文件中等等问题,这些问题大部分都是路径不对引起的。

我们进行打包之后,想运行dist文件查看打包之后的效果,此时我们可以先安装一个插件live-server -D(web提供的一个小服务器,用于测试),然后在package.json中加入一个测试的配置项,代码如下:

"scripts":{"start":"live-server ./dist"  // 运行托管在dist文件夹下的文件
}

设置环境变量进行线上和开发的url地址动态切换。插件(DefinePlugin)

在开发中我们需要请求测试环境的url,在生产环境中我们需要请求生产环境的url,此时,我们就会用到webpack的一个内置插件来为我们设置环境变量,以此来设置不同的环境变量进行请求不同的url地址,这个内置插件要在webpack.dev.js 和webpack,prod,js中配置

const webpack=require('webpack')plugins:[new webpack.DefinePlugin({ENV:'true'})
]

使用devserver解决跨域问题

跨域是浏览器的同源策略导致的,只有浏览器请求才会发生同源策略,服务器和服务器之间请求不存在跨域现象

http proxy解决跨域,就是浏览器请求devserver服务器,然后devserver服务器转发请求去请求服务器解决跨域

在webpack.dev.js的devServer中加入属性proxy,代理代码如下:

devServer:{proxy:{'/api':{target:'http://10.35.23.11',  //请求的地址指向这个urlsecure:false, //如果是https接口,需要配置为truechangeOrigin:true,  //如果接口跨域,需要进行此参数配置pathRewrite:{     //地址重写,冒号后面的可以替代冒号后面的'^/api':''}}}
}

cros解决跨域,是由后端解决设置

HMR的使用技巧

需要对某个模块进行热更新的时候,我们为了增加开发体验,我们可以通过module.hot.accept方法进行文件监视,只要模块内容发生变化,就会触发回调函数,从而可以重新读取模块内容,做对应的操作,代码如下:

if(module.hot){module.hot.accept('./hot.js(监听的文件)',function(){console.log('改变')let str = require('./hot.js')console.log(str)})
}

webpack的优化

production模式打包自带优化,最主要的是三种优化方式,

tree shaking :通常用于包的移除,在js中未被引用的代码,它依赖于ES6模块系统中的import 和 export 的静态结构特性,开发时引用一个模块后,如果只使用其中一个功能,上线打包时只会把用到的功能打包进build中,其他没用到的功能都不会引用进来,可以实现最基础的优化,如果使用commonJS规范中的require语法进行引用,则不会触发tree shaking功能

scope hoisting :作用是将模块之间的关系进行结果推测,可以让webpack打包出来的代码文件更小,运行的更快,原理就是分析模块之间的关系,尽可能的将打算的模块合并到一个函数中,但前提是不能造成代码冗余,只有那些被引用了一次的模块才会被合并,源码必须使用ES6语句,否则不会被生效。

css优化

不让css存在html的style中,将css样式提取到单独的文件中,我们需要用到插件 mini-css-extract-plugin,对每个包含css的js文件都会创建一个CSS文件,支持按需加载css和sourceMap,

只能用在webpack4中,有如下优势:

  • 异步加载

  • 不重复编译,性能很好

  • 容易使用

  • 只针对CSS

使用方法:

  1. 安装

    npm i -D mini-css-extract-plugin

  2. 在webpack配置文件中引入插件

    const MiniCssExtractPlugin = require('mini-css-extract-plugin')
  3. 创建插件对象,配置抽离的css文件名,支持placeholder语法

    new MiniCssExtractPlugin({filename: '[name].css'
    })
  4. 将原来配置的所有style-loader替换为MiniCssExtractPlugin.loader

    {
    test: /\.css$/,
    // webpack读取loader时 是从右到左的读取, 会将css文件先交给最右侧的loader来处理
    // loader的执行顺序是从右到左以管道的方式链式调用
    // css-loader: 解析css文件
    // style-loader: 将解析出来的结果 放到html中, 使其生效
    // use: ['style-loader', 'css-loader']
    use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader']
    },
    // { test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader'] },
    { test: /\.less$/, use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader'] },
    // { test: /\.s(a|c)ss$/, use: ['style-loader', 'css-loader', 'sass-loader'] },
    { test: /\.s(a|c)ss$/, use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'] },

自动添加css前缀

使用postcss,需要用到postcss-loaderautoprefixer插件

  1. 安装

    npm i -D postcss-loader autoprefixer

  2. 修改webpack配置文件中的loader,将postcss-loader放置在css-loader的右边(调用链从右到左)

    {
    test: /\.css$/,
    // webpack读取loader时 是从右到左的读取, 会将css文件先交给最右侧的loader来处理
    // loader的执行顺序是从右到左以管道的方式链式调用
    // css-loader: 解析css文件
    // style-loader: 将解析出来的结果 放到html中, 使其生效
    // use: ['style-loader', 'css-loader']
    use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader']
    },
    // { test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader'] },
    { test: /\.less$/, use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'less-loader'] },
    // { test: /\.s(a|c)ss$/, use: ['style-loader', 'css-loader', 'sass-loader'] },
    { test: /\.s(a|c)ss$/, use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'sass-loader'] },
  3. 项目根目录下添加postcss的配置文件:postcss.config.js

  4. postcss的配置文件中使用插件

    module.exports = {plugins: [require('autoprefixer')]
    }

开启css压缩

压缩css时,必须也要设置js压缩,否则它会把默认的js压缩设置覆盖。

需要使用optimize-css-assets-webpack-plugin插件来完成css压缩

但是由于配置css压缩时会覆盖掉webpack默认的优化配置,导致JS代码无法压缩,所以还需要手动把JS代码压缩插件导入进来:terser-webpack-plugin

  1. 安装

    npm i -D optimize-css-assets-webpack-plugin terser-webpack-plugin

  2. 导入插件

    const TerserJSPlugin = require('terser-webpack-plugin')
    const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
  3. 在webpack配置文件中添加配置节点

    optimization: {minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})],
    },

tips: webpack4默认采用的JS压缩插件为:uglifyjs-webpack-plugin,在mini-css-extract-plugin上一个版本中还推荐使用该插件,但最新的v0.6中建议使用teser-webpack-plugin来完成js代码压缩,具体原因未在官网说明,我们就按照最新版的官方文档来做即可

js代码分离

Code Splitting是webpack打包时用到的重要的优化特性之一,此特性能够把代码分离到不同的 bundle 中,然后可以按需加载或并行加载这些文件。代码分离可以用于获取更小的 bundle,以及控制资源加载优先级,如果使用合理,会极大影响加载时间。

有三种常用的代码分离方法:

  • 入口起点(entry points):使用entry配置手动地分离代码。

  • 防止重复(prevent duplication):使用 SplitChunksPlugin去重和分离 chunk。

  • 动态导入(dynamic imports):通过模块的内联函数调用来分离代码。

手动配置多入口

  1. 在webpack配置文件中配置多个入口

    entry: {main: './src/main.js',other: './src/other.js'
    },
    output: {// path.resolve() : 解析当前相对路径的绝对路径// path: path.resolve('./dist/'),// path: path.resolve(__dirname, './dist/'),path: path.join(__dirname, '..', './dist/'),// filename: 'bundle.js',filename: '[name].bundle.js',publicPath: '/'
    },
  2. 在main.js和other.js中都引入同一个模块,并使用其功能

    main.js

    import $ from 'jquery'
    ​
    $(function() {$('<div></div>').html('main').appendTo('body')
    })

    other.js

    import $ from 'jquery'
    ​
    $(function() {$('<div></div>').html('other').appendTo('body')
    })
  3. 修改package.json的脚本,添加一个使用dev配置文件进行打包的脚本(目的是不压缩代码检查打包的bundle时更方便)

    "scripts": {"build": "webpack --config ./build/webpack.prod.js","dev-build": "webpack --config ./build/webpack.dev.js"
    }
  4. 运行npm run dev-build,进行打包

  5. 查看打包后的结果,发现other.bundle.js和main.bundle.js都同时打包了jQuery源文件

这种方法存在一些问题:

  • 如果入口 chunks 之间包含重复的模块,那些重复模块都会被引入到各个 bundle 中。

  • 这种方法不够灵活,并且不能将核心应用程序逻辑进行动态拆分代码。

抽取公共代码

tips: Webpack v4以上使用的插件为SplitChunksPlugin,以前使用的CommonsChunkPlugin已经被移除了,最新版的webpack只需要在配置文件中的optimization节点下添加一个splitChunks属性即可进行相关配置

  1. 修改webpack配置文件

    optimization: {splitChunks: {chunks: 'all'}
    },
  2. 运行npm run dev-build重新打包

  3. 查看dist目录

     

  4. 查看vendors~main~other.bundle.js,其实就是把都用到的jQuery打包到了一个单独的js中

动态导入 (懒加载)

webpack4默认是允许import语法动态导入的,但是需要babel的插件支持,最新版babel的插件包为:@babel/plugin-syntax-dynamic-import,以前老版本不是@babel开头,已经无法使用,需要注意

动态导入最大的好处是实现了懒加载,用到哪个模块才会加载哪个模块,可以提高SPA应用程序的首屏加载速度,Vue、React、Angular框架的路由懒加载原理一样

  1. 安装babel插件

    npm install -D @babel/plugin-syntax-dynamic-import

  2. 修改.babelrc配置文件,添加@babel/plugin-syntax-dynamic-import插件

    {"presets": ["@babel/env"],"plugins": ["@babel/plugin-proposal-class-properties","@babel/plugin-transform-runtime","@babel/plugin-syntax-dynamic-import"]
    }
  3. 将jQuery模块进行动态导入

    function getComponent() {return import('jquery').then(({ default: $ }) => {return $('<div></div>').html('main')})
    }
  4. 给某个按钮添加点击事件,点击后调用getComponent函数创建元素并添加到页面

    window.onload = function () {document.getElementById('btn').onclick = function () {getComponent().then(item => {item.appendTo('body')})}
    }

SplitChunksPlugin配置参数

webpack4之后,使用SplitChunksPlugin插件替代了以前CommonsChunkPlugin

SplitChunksPlugin的配置,只需要在webpack配置文件中的optimization节点下的splitChunks进行修改即可,如果没有任何修改,则会使用默认配置

默认的SplitChunksPlugin 配置适用于绝大多数用户

webpack 会基于如下默认原则自动分割代码:

  • 公用代码块或来自 node_modules 文件夹的组件模块。

  • 打包的代码块大小超过 30k(最小化压缩之前)。

  • 按需加载代码块时,同时发送的请求最大数量不应该超过 5。

  • 页面初始化时,同时发送的请求最大数量不应该超过 3。

以下是SplitChunksPlugin的默认配置:

module.exports = {//...optimization: {splitChunks: {chunks: 'async', // 只对异步加载的模块进行拆分,可选值还有all | initialminSize: 30000, // 模块最少大于30KB才拆分maxSize: 0,  // 模块大小无上限,只要大于30KB都拆分minChunks: 1, // 模块最少引用一次才会被拆分maxAsyncRequests: 5, // 异步加载时同时发送的请求数量最大不能超过5,超过5的部分不拆分maxInitialRequests: 3, // 页面初始化时同时发送的请求数量最大不能超过3,超过3的部分不拆分automaticNameDelimiter: '~', // 默认的连接符name: true, // 拆分的chunk名,设为true表示根据模块名和CacheGroup的key来自动生成,使用上面连接符连接cacheGroups: { // 缓存组配置,上面配置读取完成后进行拆分,如果需要把多个模块拆分到一个文件,就需要缓存,所以命名为缓存组vendors: { // 自定义缓存组名test: /[\\/]node_modules[\\/]/, // 检查node_modules目录,只要模块在该目录下就使用上面配置拆分到这个组priority: -10 // 权重-10,决定了哪个组优先匹配,例如node_modules下有个模块要拆分,同时满足vendors和default组,此时就会分到vendors组,因为-10 > -20},default: { // 默认缓存组名minChunks: 2, // 最少引用两次才会被拆分priority: -20, // 权重-20reuseExistingChunk: true // 如果主入口中引入了两个模块,其中一个正好也引用了后一个,就会直接复用,无需引用两次}}}}
};

noParse

在引入一些第三方模块时,例如jQuery、bootstrap等,我们知道其内部肯定不会依赖其他模块,因为最终我们用到的只是一个单独的js文件或css文件

所以此时如果webpack再去解析他们的内部依赖关系,其实是非常浪费时间的,我们需要阻止webpack浪费精力去解析这些明知道没有依赖的库

可以在webpack配置文件的module节点下加上noParse,并配置正则来确定不需要解析依赖关系的模块

module: {noParse: /jquery|bootstrap/
}

IgnorePlugin

在引入一些第三方模块时,例如moment,内部会做i18n国际化处理,所以会包含很多语言包,而语言包打包时会比较占用空间,如果我们项目只需要用到中文,或者少数语言,可以忽略掉所有的语言包,然后按需引入语言包

从而使得构建效率更高,打包生成的文件更小

需要忽略第三方模块内部依赖的其他模块,只需要三步:

  1. 首先要找到moment依赖的语言包是什么

  2. 使用IgnorePlugin插件忽略其依赖

  3. 需要使用某些依赖时自行手动引入

具体实现如下:

  1. 通过查看moment的源码来分析:

    function loadLocale(name) {var oldLocale = null;// TODO: Find a better way to register and load all the locales in Nodeif (!locales[name] && (typeof module !== 'undefined') &&module && module.exports) {try {oldLocale = globalLocale._abbr;var aliasedRequire = require;aliasedRequire('./locale/' + name);getSetGlobalLocale(oldLocale);} catch (e) {}}return locales[name];
    }

    观察上方代码,同时查看moment目录下确实有locale目录,其中放着所有国家的语言包,可以分析得出:locale目录就是moment所依赖的语言包目录

  2. 使用IgnorePlugin插件来忽略掉moment模块的locale目录

    在webpack配置文件中安装插件,并传入配置项

    参数1:表示要忽略的资源路径

    参数2:要忽略的资源上下文(所在哪个目录)

    两个参数都是正则对象

    new webpack.IgnorePlugin(/\.\/locale/, /moment/)
  3. 使用moment时需要手动引入语言包,否则默认使用英文

    import moment from 'moment'
    import 'moment/locale/zh-cn'
    moment.locale('zh-CN')
    console.log(moment().subtract(6, 'days').calendar())

DllPlugin

在引入一些第三方模块时,例如vue、react、angular等框架,这些框架的文件一般都是不会修改的,而每次打包都需要去解析它们,也会影响打包速度,哪怕做拆分,也只是提高了上线后用户访问速度,并不会提高构建速度,所以如果需要提高构建速度,应该使用动态链接库的方式,类似于Windows中的dll文件。

借助DllPlugin插件实现将这些框架作为一个个的动态链接库,只构建一次,以后每次构建都只生成自己的业务代码,可以大大提高构建效率!

主要思想在于,将一些不做修改的依赖文件,提前打包,这样我们开发代码发布的时候就不需要再对这部分代码进行打包,从而节省了打包时间。

涉及两个插件:

  1. DllPlugin

    使用一个单独webpack配置创建一个dll文件。并且它还创建一个manifest.json。DllReferencePlugin使用该json文件来做映射依赖性。(这个文件会告诉我们的哪些文件已经提取打包好了)

    配置参数:

    • context (可选): manifest文件中请求的上下文,默认为该webpack文件上下文。

    • name: 公开的dll函数的名称,和output.library保持一致即可。

    • path: manifest.json生成的文件夹及名字

  2. DllReferencePlugin

    这个插件用于主webpack配置,它引用的dll需要预先构建的依赖关系。

    • context: manifest文件中请求的上下文。

    • manifest: DllPlugin插件生成的manifest.json

    • content(可选): 请求的映射模块id(默认为manifest.content)

    • name(可选): dll暴露的名称

    • scope(可选): 前缀用于访问dll的内容

    • sourceType(可选): dll是如何暴露(libraryTarget)

将Vue项目中的库抽取成Dll

  1. 准备一份将Vue打包成DLL的webpack配置文件

    在build目录下新建一个文件:webpack.vue.js

    配置入口:将多个要做成dll的库全放进来

    配置出口:一定要设置library属性,将打包好的结果暴露在全局

    配置plugin:设置打包后dll文件名和manifest文件所在地

    const path = require('path')
    const webpack = require('webpack')
    module.exports = {mode: 'development',entry: {vue: ['vue/dist/vue.js','vue-router']},output: {filename: '[name]_dll.js',path: path.resolve(__dirname, '../dist'),library: '[name]_dll'},plugins: [new webpack.DllPlugin({name: '[name]_dll',path: path.resolve(__dirname, '../dist/manifest.json')})]
    }
  2. 在webpack.base.js中进行插件的配置

    使用DLLReferencePlugin指定manifest文件的位置即可

    new webpack.DllReferencePlugin({manifest: path.resolve(__dirname, '../dist/manifest.json')
    })
  3. 安装add-asset-html-webpack-plugin

    npm i add-asset-html-webpack-plugin -D

  4. 配置插件自动添加script标签到HTML中

    new AddAssetHtmlWebpackPlugin({filepath: path.resolve(__dirname, '../dist/vue_dll.js')
    })

将React项目中的库抽取成Dll

  1. 准备一份将React打包成DLL的webpack配置文件

    在build目录下新建一个文件:webpack.vue.js

    配置入口:将多个要做成dll的库全放进来

    配置出口:一定要设置library属性,将打包好的结果暴露在全局

    配置plugin:设置打包后dll文件名和manifest文件所在地

    const path = require('path')
    const webpack = require('webpack')
    module.exports = {mode: 'development',entry: {react: ['react','react-dom']},output: {filename: '[name]_dll.js',path: path.resolve(__dirname, '../dist'),library: '[name]_dll'},plugins: [new webpack.DllPlugin({name: '[name]_dll',path: path.resolve(__dirname, '../dist/manifest.json')})]
    }
  2. 在webpack.base.js中进行插件的配置

    使用DLLReferencePlugin指定manifest文件的位置即可

    new webpack.DllReferencePlugin({manifest: path.resolve(__dirname, '../dist/manifest.json')
    })
  3. 安装add-asset-html-webpack-plugin

    npm i add-asset-html-webpack-plugin -D

  4. 配置插件自动添加script标签到HTML中

    new AddAssetHtmlWebpackPlugin({filepath: path.resolve(__dirname, '../dist/react_dll.js')
    })

Happypack

由于webpack在node环境中运行打包构建,所以是单线程的模式,在打包众多资源时效率会比较低下,早期可以通过Happypack来实现多进程打包。当然,这个问题只出现在低版本的webpack中,现在的webpack性能已经非常强劲了,所以无需使用Happypack也可以实现高性能打包

Happypack官网

引用官网原文:

Maintenance mode notice

My interest in the project is fading away mainly because I'm not using JavaScript as much as I was in the past. Additionally, Webpack's native performance is improving and (I hope) it will soon make this plugin unnecessary.

See the FAQ entry about Webpack 4 and thread-loader.

Contributions are always welcome. Changes I make from this point will be restricted to bug-fixing. If someone wants to take over, feel free to get in touch.

Thanks to everyone who used the library, contributed to it and helped in refining it!!!

由此可以看出作者已经发现,webpack的性能已经强大到不需要使用该插件了,而且小项目使用该插件反而会导致性能损耗过大,因为开启进程是需要耗时的

使用方法:

  1. 安装插件

    npm i -D happypack

  2. 在webpack配置文件中引入插件

    const HappyPack = require('happypack')
  3. 修改loader的配置规则

    {test: /.js$/,use: {loader: 'happypack/loader'},include: path.resolve(__dirname, '../src'),exclude: /node_modules/
    }
  4. 配置插件

    new HappyPack({loaders: [ 'babel-loader' ]
    })
  5. 运行打包命令

    npm run build

浏览器缓存

在做了众多代码分离的优化后,其目的是为了利用浏览器缓存,达到提高访问速度的效果,所以构建项目时做代码分割是必须的,例如将固定的第三方模块抽离,下次修改了业务代码,重新发布上线不重启服务器,用户再次访问服务器就不需要再次加载第三方模块了

但此时会遇到一个新的问题,如果再次打包上线不重启服务器,客户端会把以前的业务代码和第三方模块同时缓存,再次访问时依旧会访问缓存中的业务代码,所以会导致业务代码也无法更新

需要在output节点的filename中使用placeholder语法,根据代码内容生成文件名的hash:

output: {// path.resolve() : 解析当前相对路径的绝对路径// path: path.resolve('./dist/'),// path: path.resolve(__dirname, './dist/'),path: path.join(__dirname, '..', './dist/'),// filename: 'bundle.js',filename: '[name].[contenthash:8].bundle.js',publicPath: '/'},

之后每次打包业务代码时,如果有改变,会生成新的hash作为文件名,浏览器就不会使用缓存了,而第三方模块不会重新打包生成新的名字,则会继续使用缓存

打包分析

项目构建完成后,需要通过一些工具对打包后的bundle进行分析,通过分析才能总结出一些经验,官方推荐的分析方法有两步完成:

  1. 使用--profile --json参数,以json格式来输出打包后的结果到某个指定文件中

    webpack --profile --json > stats.json

  2. 将stats.json文件放入工具中进行分析

    官方工具:official analyze tool

    官方推荐的其他四个工具:

    • webpack-chart

    • webpack-visualizer

    • webpack-bundle-analyzer

    • webpack bundle optimize helper

    其中webpack-bundle-analyzer是一个插件,可以以插件的方式安装到项目中

Prefetching和Preloading

在优化访问性能时,除了充分利用浏览器缓存之外,还需要涉及一个性能指标:coverage rate(覆盖率)

可以在Chrome浏览器的控制台中按:ctrl + shift + p,查找coverage,打开覆盖率面板

开始录制后刷新网页,即可看到每个js文件的覆盖率,以及总的覆盖率

想提高覆盖率,需要尽可能多的使用动态导入,也就是懒加载功能,将一切能使用懒加载的地方都是用懒加载,这样可以大大提高覆盖率

但有时候使用懒加载会影响用户体验,所以可以在懒加载时使用魔法注释:Prefetching,是指在首页资源加载完毕后,空闲时间时,将动态导入的资源加载进来,这样即可以提高首屏加载速度,也可以解决懒加载可能会影响用户体验的问题,一举两得!

function getComponent() {return import(/* webpackPrefetch: true */ 'jquery').then(({ default: $ }) => {return $('<div></div>').html('我是main')})
}

第5章 webpack原理

学习目标

  • 了解webpack打包原理

  • 了解webpack的loader原理

  • 了解webpack的插件原理

  • 了解ast抽象语法树的应用

  • 了解tapable的原理

  • 手写一个简单的webpack

项目准备工作

  1. 新建一个项目,起一个炫酷的名字

  2. 新建bin目录,将打包工具主程序放入其中

    主程序的顶部应当有:#!/usr/bin/env node标识,指定程序执行环境为node

  3. package.json中配置bin脚本

    {"bin": "./bin/itheima-pack.js"
    }
  4. 通过npm link链接到全局包中,供本地测试使用

分析webpack打包的bundle文件

其内部就是自己实现了一个__webpack_require__函数,递归导入依赖关系

(function (modules) { // webpackBootstrap// The module cachevar installedModules = {};
​// The require functionfunction __webpack_require__(moduleId) {
​// Check if module is in cacheif (installedModules[moduleId]) {return installedModules[moduleId].exports;}// Create a new module (and put it into the cache)var module = installedModules[moduleId] = {i: moduleId,l: false,exports: {}};
​// Execute the module functionmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
​// Flag the module as loadedmodule.l = true;
​// Return the exports of the modulereturn module.exports;}
​// Load entry module and return exportsreturn __webpack_require__(__webpack_require__.s = "./src/index.js");
})({"./src/index.js":(function (module, exports, __webpack_require__) {eval("let news = __webpack_require__(/*! ./news.js */ \"./src/news.js\")\r\nconsole.log(news.content)\n\n//# sourceURL=webpack:///./src/index.js?");}),"./src/message.js":(function (module, exports) {eval("module.exports = {\r\n  content: '今天要下雨了!!!'\r\n}\n\n//# sourceURL=webpack:///./src/message.js?");}),"./src/news.js":(function (module, exports, __webpack_require__) {eval("let message = __webpack_require__(/*! ./message.js */ \"./src/message.js\")\r\n\r\nmodule.exports = {\r\n  content: '今天有个大新闻,爆炸消息!!!内容是:' + message.content\r\n}\n\n//# sourceURL=webpack:///./src/news.js?");})});

自定义loader

在学习给自己写的itheima-pack工具添加loader功能之前,得先学习webpack中如何自定义loader,所以学习步骤分为两大步:

  1. 掌握自定义webpack的loader

  2. 学习给itheima-pack添加loader功能并写一个loader

webpack以及我们自己写的itheima-pack都只能处理JavaScript文件,如果需要处理其他文件,或者对JavaScript代码做一些操作,则需要用到loader。

loader是webpack中四大核心概念之一,主要功能是将一段匹配规则的代码进行加工处理,生成最终的代码后输出,是webpack打包环节中非常重要的一环。

loader 可以将所有类型的文件转换为 webpack 能够处理的有效模块,然后你就可以利用 webpack 的打包能力,对它们进行处理。

之前都使用过别人写好的loader,步骤大致分为:

  1. 装包

  2. 在webpack.config.js中配置module节点下的rules即可,例如babel-loader(省略其他配置,只论loader)

  3. (可选步骤)可能还需要其他的配置,例如babel需要配置presets和plugin

const path = require('path')
​
module.exports = {entry: './src/index.js',output: {path: path.join(__dirname, 'dist'),filename: 'bundle.js'},module: {rules: [{ test: /\.js$/, use: 'babel-loader' }]},mode: 'development'
}

实现一个简单的loader

loader到底是什么东西?能不能自己写?

答案是肯定的,loader就是一个函数,同样也可以自己来写

  1. 在项目根目录中新建一个目录存放自己写的loader:

 

  1. 编写myloader.js,其实loader就是对外暴露一个函数

    第一个参数就是loader要处理的代码

    module.exports = function(source) {console.log(source) // 只是简单打印并返回结果,不作任何处理return source
    }
  2. 同样在webpack.config.js中配置自己写的loader,为了方便演示,直接匹配所有的js文件使用自己的myloader进行处理

    const path = require('path')
    ​
    module.exports = {entry: './src/index.js',output: {path: path.join(__dirname, 'dist'),filename: 'bundle.js'},module: {rules: [{ test: /.js$/, use: './loaders/myloader.js' }]},mode: 'development'
    }
  3. 如果需要实现一个简单的loader,例如将js中所有的“今天”替换成“明天”

    只需要修改myloader.js的内容如下即可

    module.exports = function(source) {return source.replace(/今天/g, '明天')
    }
  4. 同时也可以配置多个loader对代码进行处理

    const path = require('path')
    ​
    module.exports = {entry: './src/index.js',output: {path: path.join(__dirname, 'dist'),filename: 'bundle.js'},module: {rules: [{ test: /.js$/, use: ['./loaders/myloader2.js', './loaders/myloader.js'] }]},mode: 'development'
    }
  5. myloader2.js

    module.exports = function(source) {return source.replace(/爆炸/g, '小道')
    }

loader的分类

不同类型的loader加载时优先级不同,优先级顺序遵循:

前置 > 行内 > 普通 > 后置

pre: 前置loader

post: 后置loader

指定Rule.enforce的属性即可设置loader的种类,不设置默认为普通loader

在itheima-pack中添加loader的功能

通过配置loader和手写loader可以发现,其实webpack能支持loader,主要步骤如下:

  1. 读取webpack.config.js配置文件的module.rules配置项,进行倒序迭代(rules的每项匹配规则按倒序匹配)

  2. 根据正则匹配到对应的文件类型,同时再批量导入loader函数

  3. 倒序迭代调用所有loader函数(loader的加载顺序从右到左,也是倒叙)

  4. 最后返回处理后的代码

在实现itheima-pack的loader功能时,同样也可以在加载每个模块时,根据rules的正则来匹配是否满足条件,如果满足条件则加载对应的loader函数并迭代调用

depAnalyse()方法中获取到源码后,读取loader:

let rules = this.config.module.rules
for (let i = rules.length - 1; i >= 0; i--) {// console.log(rules[i])let {test, use} = rules[i]if (test.test(modulePath)) {for (let j = use.length - 1; j >= 0; j--) {let loaderPath = path.join(this.root, use[j])let loader = require(loaderPath)source = loader(source)}}
}
查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. 彻底解决Webpack打包慢的问题

    2016-08-03 09:20 转载自&#xff1a;https://segmentfault.com/a/1190000006087638?utm_sourceweekly&utm_mediumemail&utm_campaignemail_weekly这几天写腾讯实习生 Mini 项目的时候用上了 React 全家桶&#xff0c;当然同时引入了 Webpack 作为打包工具。但是开发…...

    2024/4/20 19:53:00
  2. 使用webpack打包你的web

    原文链接&#xff1a; https://blog.madewithlove.be/post/webpack-your-bags/ 打包你的web 目前为止你可能已经听说过这款名为webpack的新工具。如果你还不是很了解它&#xff0c;你可能会有一些困惑。因为有人说它是Gulp另外有人说它像Browserify。另一方面&#xff0c;如果…...

    2024/4/28 17:45:32
  3. ionic3使用百度地图

    来源&#xff1a;https://www.npmjs.com/package/angular2-baidu-map 1、安装地图插件 npm install angular2-baidu-map 安装 2、在项目src/app/app.module.ts 导入 import { BaiduMapModule } from angular2-baidu-map//NgModule的imports添加BaiduMapModule.forRoot({a…...

    2024/4/20 19:52:58
  4. ionic2 百度地图应用

    ionic2 百度地图集成 demo: https://github.com/wangzuxing/myionic2prj 1、创建项目工程(命令行方式) ionic start myionic2prj blank --v2 //--v2 参数 指示创建ionic2工程 cd myionic2prj 2、 npm install //或使用”cnpm install” 主要完成安装所需模块&#xf…...

    2024/4/20 19:52:57
  5. 百度地图滚轮缩放产生位置偏移的解决办法

    查了全网并没有任何解决办法, 但是有一段话引起我的注意: 百度地图的缩放是基于body层的 . 随后阅读地图源码发现: 但是这个fx函数我没找到被调用的地方. 然后源码看了又看, 确实实力不够哈哈找不到唉 地图定位貌似是基于body层做计算, 反正, 使用标准文档流就能解决这个问题!…...

    2024/4/21 4:13:41
  6. vue Echart热力图 百度地图

    搬运某位兄台博客的&#xff1a;https://blog.csdn.net/yc_1993/article/details/52432005 页面先引入&#xff1a;<script src"http://api.map.baidu.com/api?v2.0&ak53oVIOgmSIejwV7EfphPgTynOZbIiVYu"></script> <template><div clas…...

    2024/4/21 4:13:39
  7. html5如何引用百度地图api,WebApp如何调用百度地图API

    一、百度地图API的应用场景和方法百度地图接口有三种调用方式&#xff1a;第一种是WEB浏览器端调用(H5)&#xff1b;第二种是Android&#xff1b;第三种是IOS&#xff1b;附上文档地址&#xff1a;第一种当你调用API时会在浏览器端打开百度地图页面(Web和WebAPP打开后样子不同)…...

    2024/4/21 4:13:40
  8. iPhone6可能取代公交卡和门禁卡

    10月28日,苹果公司正在积极寻求合作,以增加iPhone 6和iPhone 6 Plus内置的NFC芯片的用途。该芯片目前只能通过Apple Pay支付服务使用,因为苹果并没有向第三方开放API(应用编程接口)。苹果正在与潜在合作伙伴展开沟通,希望利用这项技术提升安全性,甚至当做门禁卡和公交卡来…...

    2024/4/30 12:26:14
  9. echarts 百度地图扩展使用

    最近在使用echarts地图时遇到诸多问题&#xff0c;现纪录如下&#xff1a; 项目基于 "angular/cli": "~9.0.2" && "echarts": "^4.7.0"。 使用的 官方示列 &#xff0c;这个示列结合百度地图&#xff0c;在项目中引用echart…...

    2024/4/21 4:13:37
  10. 使用百度地图实现拖动定位、搜索定位

    该代码主要的技术点&#xff1a; >获取百度地图key&#xff0c;也就是ak; >拖动定位&#xff0c;经纬度、详细地址 >搜索定位&#xff0c;根据所搜索得地址进行地图地位&#xff0c;精确定位。 具体的实现代码&#xff1a; <!DOCTYPE html> <html> …...

    2024/4/21 4:13:36
  11. 百度地图使用(1)——打点、连线、添加label层

    话不多说&#xff0c;首先上代码&#xff1a; $scope.initMap function(points){var map new BMap.Map(pathTrackMap);var point new BMap.Point(113.843216,27.687262);map.centerAndZoom(point,13);//设置地图map.enableDragging();map.enableScrollWheelZoom();map.enab…...

    2024/4/21 4:13:35
  12. Angular通过CORS实现跨域方案

    以前有一篇很老的文章网上转了很多,包括现在如果你百度"跨域"这个关键字,前几个推荐的都是"Javascript跨域总结与解决方案".看了一下感觉手段有点陈旧了,有一些比如document.domain还有iframe的解决方案委实"丑陋"一些,感觉不再适用于现在一些项…...

    2024/4/29 17:54:27
  13. 百度地图开发探索 添加覆盖物(圆形、多边形、行政区)围栏 typescript angular

    添加覆盖物 话不多说&#xff0c;先上图&#xff0c;看图写代码&#xff08;添加点、弹窗的在上一章有整理&#xff09; 1、圆形围栏&#xff1a; 2、多边形围栏&#xff1a; 3、行政区围栏&#xff1a; 画图&#xff1a; 图形的展示&#xff1a; // 画围栏drawFence(fence…...

    2024/4/21 4:13:33
  14. angular2-baidu-map网站中使用百度地图

    效果图 1、安装 npm install angular2-baidu-map --save 2、在主模块中注册 app.module.ts import {BaiduMap} from "angular2-baidu-map";组件中导入 declarations: [BaiduMap ] 3、创建组件使用地图 baidu.component.ts import {Component, OnInit} from angular/c…...

    2024/4/21 4:13:31
  15. 在angular4中显示百度地图中的热力图

    最近心血来潮&#xff0c;想学学百度地图&#xff0c;请教了同事张同学&#xff0c;成果如下 1.首先在index.html中引入ak<script type"text/javascript" src"http://api.map.baidu.com/api?v2.0&akyour ak"></script>2.在.angular-cli.j…...

    2024/4/21 4:13:31
  16. 关于最新百度地图sdk如何使覆盖物固定在屏幕(MapView)中心

    关于最新百度地图sdk如何使覆盖物固定在屏幕中心 最近为了完成课程设计&#xff0c;接触了百度地图API&#xff0c;我现在用的版本是Android地图sdk v3.3.0&#xff0c;也是目前的最新发布了&#xff0c;相对于之前的版本还是有挺大的改进 先说说需求&#xff1a;我是想将覆盖…...

    2024/4/21 4:13:29
  17. 百度地图点聚合MarkerClusterer,性能优化

    参考文献&#xff1a;http://www.cnblogs.com/lightnull/p/6184867.html 百度的点聚合算法 是基于方格和距离的聚合算法&#xff0c;即开始的时候地图上没有任何已知的聚合点&#xff0c;然后遍历所有的点&#xff0c;去计算点的外包正方形&#xff08;由gridSize指定&#xff…...

    2024/4/21 4:13:29
  18. 使用Angular8和百度地图api开发《旅游清单》

    前言&#xff1a; 本文的目的是通过一步步实现一个旅游清单项目&#xff0c;让大家快速入门Angular8以及百度地图API。我们将收获&#xff1a; Angular8基本用法&#xff0c;架构 使用百度地图API实现自己的地图应用 解决调用百度地图API时的跨域问题 对localStorage进行基础封…...

    2024/4/21 4:13:27
  19. 地图无法拖动缩放

    问题描述 百度地图结合echart使用的使用过程中发现地图无法拖动和缩放&#xff0c;排除设置地图不可拖动的属性并去掉所有其他有可能挡住的元素&#xff0c;发现还是不行。 发现问题 再次排查发现&#xff0c;去掉相关样式是可以实现拖动的&#xff0c;定位到应该是由样式z…...

    2024/4/21 4:13:26
  20. 百度地图之 区域划分、在线人员点标记、点每个标记点,弹出对应的信息

    在线人员&#xff0c;箭头指向的分别是一级是镇的整体在线人员&#xff0c;二级菜单指的的村的在线人员 有区域划分、自定义弹窗信息<template><div class"contentHome"><div class"forest" click"froest"><img class"…...

    2024/4/21 4:13:25

最新文章

  1. 【Java探索之旅】包管理精粹 Java中包的概念与实践

    文章目录 &#x1f4d1;前言一、封装1.1 封装的概念1.2 访问限定修饰符 二、封装扩展&#xff08;包&#xff09;2.1 包的概念2.2 带入包中的类2.3 自定义包2.4 常见的包 &#x1f324;️全篇总结 &#x1f4d1;前言 在Java编程中&#xff0c;封装是面向对象编程的核心概念之一…...

    2024/5/2 2:15:02
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. 图像处理相关知识 —— 椒盐噪声

    椒盐噪声是一种常见的图像噪声类型&#xff0c;它会在图像中随机地添加黑色&#xff08;椒&#xff09;和白色&#xff08;盐&#xff09;的像素点&#xff0c;使图像的质量降低。这种噪声模拟了在图像传感器中可能遇到的问题&#xff0c;例如损坏的像素或传输过程中的干扰。 椒…...

    2024/5/1 13:08:22
  4. 前端学习<二>CSS基础——17-CSS3的常见边框汇总

    CSS3 常见边框汇总 <!DOCTYPE html><html lang"en"><head><meta charset"UTF-8"><title>CSS3 边框</title><style>body, ul, li, dl, dt, dd, h1, h2, h3, h4, h5 {margin: 0;padding: 0;}​body {background-c…...

    2024/5/1 13:58:41
  5. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/5/1 17:30:59
  6. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/4/30 18:14:14
  7. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/4/29 2:29:43
  8. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/4/30 18:21:48
  9. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/4/27 17:58:04
  10. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/4/27 14:22:49
  11. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/4/28 1:28:33
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/4/30 9:43:09
  13. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/4/27 17:59:30
  14. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/4/25 18:39:16
  15. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/4/28 1:34:08
  16. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/4/26 19:03:37
  17. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/4/29 20:46:55
  18. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/4/30 22:21:04
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/5/1 4:32:01
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/4/27 23:24:42
  21. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/4/28 5:48:52
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/4/30 9:42:22
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/4/30 9:43:22
  24. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/4/30 9:42:49
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57