关于chrome:前端请求后端数据有哪些方法

在前后端拆散的开发我的项目中,前后端联调的时候会呈现这样那样的问题,尤其是在调取数据的程序下面,有时候前端给的前端给到后端的明明是正确的但就是无奈拿到正确的数据,上面小千就来给大家详解一下常见的三种数据传输方式。 1、地址栏传输数据 1)、query string Parameters: 当申请形式是get时,浏览器会应用查问字符串的形式进行传递数据,即:query string Parameters 查问字符串的规定:申请参数应用 URL地址和“问号传参“ 的形式进行传递----用问号把url和申请参数离开。 申请参数的格局:以键值对的形式体现,多个键值对之间用&隔开。 假如:申请地址为 newsList.php。申请参数是pageIndex和pageCount。 那么,申请的格局为:newsList.php?pageIndex=1&pageCount=10;如下图,申请形式为get,在chrome浏览器的network里看到的是:query string Parameters1 2、 申请体中传输数据 当申请形式不是get(大部分状况是post或put)时,那么申请的数据不是在url上,而是在申请体里。申请体的英文就是:www.diuxie.comrequest payload。然而chrome浏览器针对不同的content-type有做了辨别,别离是formData和request payload。 1)、formData content-type的值是" application/x-www-form-urlencoded"或者 multipart/form-data; boundary=----WebKitFormBoundaryBoMA1XQDUpwpxKQg 时,那么,就是用的是formData的格局传递数据2 3 2)、request payload content-type的值是" text/plain"或者"application/json" 时,那么,就是用的是request payload的格局[游戏](http://www.diuxie.com)传递数据4 5 附:默认的数据格式 1、传统的ajax申请时候,Content-Type默认为"文本"类型。 2、传统的form提交的时候,Content-Type默认为"Form"类型( application/x-www-form-urlencoded ) 3、axios传递字符串的时候,Content-Type默认为"Form"类型( application/x-www-form-urlencoded ) 4、axios传递对象的时候,Content-Type默认为"JSON"类型(( application/json) 以上就是前端三种传输数据的形式了

May 31, 2021 · 1 min · jiezi

关于chrome:SpringBoot-启动过程执行某函数

1、实现ServletContextAware接口并重写其setServletContext办法 @Componentpublic class TestStarted implements ServletContextAware { /** * 在填充一般bean属性之后但在初始化之前调用 * 相似于initializingbean的afterpropertiesset或自定义init办法的回调 * */@Overridepublic void setServletContext(ServletContext servletContext) { System.out.println("setServletContext办法");留神:该办法会在填充完一般Bean的属性,然而还没有进行游戏Bean的初始化之前执行 2、实现ServletContextListener接口 /**java我的项目www fhadmin org 在初始化Web应用程序中的任何过滤器或servlet之前,将告诉所有servletContextListener上下文初始化。 */@Overridepublic void contextInitialized(ServletContextEvent sce) { //ServletContext servletContext = sce.getServletContext();System.out.println("执行contextInitialized办法");3、将要执行的办法所在的类交个spring容器扫描(@Component),并且在要执行的办法上增加@PostConstruct注解或者动态代码块执行 //java我的项目www fhadmin org@Componentpublic class Test2 { //动态代码块会在依赖注入后主动执行,并优先执行static{ System.out.println("---static--");}/** * @Postcontruct’在依赖注入实现后主动调用 */www.sangpi.com@PostConstructpublic static void haha(){ System.out.println("@Postcontruct’在依赖注入实现后主动调用");4、实现ApplicationRunner接口 /**java我的项目www fhadmin org 用于批示bean蕴含在SpringApplication中时应运行的接口。能够定义多个applicationrunner bean在同一应用程序上下文中,能够应用有序接口或@order正文对其进行排序。 */@Overridepublic void run(ApplicationArguments args) throws Exception { System.out.println("ApplicationRunner的run办法");5、实现CommandLineRunner接口 /** 用于批示bean蕴含在SpringApplication中时应运行的接口。能够在同一应用程序上下文中定义多个commandlinerunner bean,并且能够应用有序接口或@order正文对其进行排序。如果须要拜访applicationArguments而不是原始字符串数组,请思考应用applicationrunner。java我的项目 */@Overridepublic void run(String... ) throws Exception { System.out.println("CommandLineRunner的run办法");}

May 31, 2021 · 1 min · jiezi

关于chrome:您的连接不是私密连接

降级chrome到最新版,无奈关上自签名证书的网站了。如公司的堡垒机强制走https,但用的是本人签发的证书,这就喜剧了。https://blj.jdb-dev.com/admin... 解决办法是在以后页面输出:thisisunsafe,页面会主动刷新就行了。这是chrome留的一个后门。还一种方法是在console输出: sendCommand(SecurityInterstitialCommandId.CMD_PROCEED)详见这篇文章,解释的比较清楚:https://www.jianshu.com/p/7a7...

May 27, 2021 · 1 min · jiezi

关于chrome:合理的游戏开发流程应该是这样

这篇文章分享开发流程标准,目标是进步产品质量,优化开发流程,供大家参考。 标准是死的,人是活的,心愿本人定的标准,不要被打脸。 接下来从以上六个阶段进行逐个拆解。 1 需要评审作为技术人员必定都加入过需要评审会,不晓得有没有遇到这样的状况? 产品经理依照 PRD 文档读一遍,参会人员金石为开。 产品经理刚讲了一个需要点,参会人员就产生了强烈的探讨,都在证实本人是对的。 参会人员对需要的指标不明确,对需要点进行发散思维探讨,最终偏离方向。 遇到以上问题,必定是在加入需要评审之前未做充分准备,那么问题来了,须要提前准备什么? 评审前 不要听产品同学说,该需要是大老板跟进的、十分重要、十分紧急之类的,就问产品三个问题: 解决了什么问题? 晋升了什么指标? 有什么商业价值? 这三个问题搞清楚了,再进行评审。 产品经理收回 原型 和 PRD 初稿后,开发人员要有 1-2 天工夫(具体工夫依据我的项目大小而定),相熟文档,有任何疑难能够反馈给开发经理,由开发经理对立收集再反馈给产品经理,产品经理逐个进行答疑。 相熟完文档后,开发人员和开发经理须要一起确定: 技术选型(前端/后端框架、日志中间件、消息中间件、数据库...) 技术架构(组件与组件之间如何协同工作,如何部署) 技术难点预知(明确存在的技术难点,并确定解决方案) 性能瓶颈预知(明确可能存在性能瓶颈的中央,并确定应答措施) 上下游零碎交互(明确在流程中的哪个地位,约定接口文档提供工夫、接口联调工夫) 功能模块划分(工作拆分和调配) 技术计划确定后,须要输入技术设计文档,包含:总体设计、概要设计、具体设计、接口设计 等。 评审中 开发人员必须加入,有需要不明确的中央当场提出,同时开发人员也须要思考产品需要是否正当,可适当提出本人的产品意见。 个别评审至多有两次(初稿和终稿)。 评审后 评审后,如有需更新技术文档的请及时进行更新。 开发经理首先须要思考团队现有的资源及我的项目的优先级,而后依据技术设计文档进行评估排期。 排期模板如下: 2 技术评审评审前 开发人员肯定要器重技术设计! 开发人员肯定要器重技术设计! 开发人员肯定要器重技术设计! 重要事件说三遍! 技术评审次要评审什么? 零碎关系图、模块关系图、流程图的设计,画图工具依据本人喜好即可。 接口设计,须要思考接口的 兼容性、扩展性、参数命名恪守 参数命名标准 等。 数据库设计,须要恪守 数据库设计规范,并记录 数据表变更文档。 具体设计,须要思考公共类、公共办法、办法定义 恪守 我的项目框架目录标准。 评审中 开发人员和开发经理必须加入,波及到总体设计和概要设计时,须要邀请 架构师 参加,波及到数据库调整时,须要邀请 DBA 参加。 个别评审至多有两次(初稿和终稿)。 评审后 评审后,如有需更新排期文档的请及时进行游戏更新。 排期确定后,通过邮件形式进行回复排期,应用标准化的 回复排期邮件模板。 ...

May 21, 2021 · 1 min · jiezi

关于chrome:Chrome源码顶级目录

Chrome源码顶级目录android_webview:提供实用于集成到android平台的src / content外观。不适用于单个android应用程序(APK)。无关Android WebView源代码组织的更多信息。apps:Chrome打包的应用程序。base:在所有子项目之间共享的通用代码。其中蕴含诸如字符串操作,通用实用程序等内容。仅当必须在多个其余顶级我的项目之间共享时,才在此处增加内容。breakpad:Google的开源解体报告我的项目。这是间接从Google Code的Subversion存储库中提取的。build:所有我的项目共享的与构建相干的配置。cc:Chromium合成器实现。chrome:Chromium浏览器(请参见下文)。chrome / test / data:用于运行某些测试的数据文件。components:目录,用于将内容模块作为其所依赖的最上层的组件。内容: 多过程沙盒浏览器所需的外围代码(请参见下文)。 无关为什么咱们拆散出此代码的更多信息。设施:常见的低级硬件API的跨平台形象。net:为Chromium开发的网络库。在存储库中运行咱们简略的test_shell时,能够将其与Chromium离开应用webkit。另请参阅chrome/common/net。sandbox:沙盒我的项目,它试图避免被黑的渲染器批改零碎。skia + third_party / skia:Google的Skia图形库。ui / gfx中的其余类包装Skia。sql:咱们盘绕sqlite。测试:蕴含咱们用于单元测试的Google开源GTest代码。third_party:200多个小型和大型“内部”库,例如图像解码器,压缩库和Web引擎Blink(此处是因为它继承自WebKit的许可证限度)。 增加新软件包。... / blink / renderer:负责将HTML,CSS和脚本转换为绘画命令和其余状态更改的Web引擎。工具ui / gfx:共享的图形类。这些形成了Chromium UI图形的根底。ui / views:一个简略的框架,用于进行UI开发,提供渲染,布局和事件处理。大多数浏览器用户界面都是在此零碎中实现的。该目录蕴含根底对象。其余一些特定于浏览器的对象位于chrome / browser / ui / views中。url:Google的开源URL解析和规范化库。v8:V8 Javascript库。这是间接从Google Code的Subversion存储库中提取的。

May 19, 2021 · 1 min · jiezi

关于chrome:GN-Reference

GN ReferenceThis page is automatically generated from gn help --markdown all. --args: Specifies build arguments overrides. See "gn help buildargs" for an overview of how build arguments work. Most operations take a build directory. The build arguments are taken from the previous build done in that directory. If a command specifies --args, it will override the previous arguments stored in the build directory, and use the specified ones. The args specified will be saved to the build directory for subsequent commands. Specifying --args="" will clear all build arguments.Formatting The value of the switch is interpreted in GN syntax. For typical usage of string arguments, you will need to be careful about escaping of quotes.Examples gn gen out/Default --args="foo=\"bar\"" gn gen out/Default --args='foo="bar" enable=true blah=7' gn check out/Default --args="" Clears existing build args from the directory. gn desc out/Default --args="some_list=[1, false, \"foo\"]"--[no]color: Forces colored output on or off. Normally GN will try to detect whether it is outputting to a terminal and will enable or disable color accordingly. Use of these switches will override the default.Examples gn gen out/Default --color gn gen out/Default --nocolor--dotfile: Override the name of the “.gn” file. Normally GN loads the ".gn"file from the source root for some basic configuration (see "gn help dotfile"). This flag allows you to use a different file. Note that this interacts with "--root" in a possibly incorrect way. It would be nice to test the edge cases and document or fix.--markdown: write the output in the Markdown format.--[no]color: Forces colored output on or off. Normally GN will try to detect whether it is outputting to a terminal and will enable or disable color accordingly. Use of these switches will override the default.Examples gn gen out/Default --color gn gen out/Default --nocolor-q: Quiet mode. Don't print output on success. This is useful when running as a part of another script.--root: Explicitly specify source root. Normally GN will look up in the directory tree from the current directory to find a ".gn" file. The source root directory specifies the meaning of "//" beginning with paths, and the BUILD.gn file in that directory will be the first thing loaded. Specifying --root allows GN to do builds in a specific directory regardless of the current directory.Examples gn gen //out/Default --root=/home/baracko/src gn desc //out/Default --root="C:\Users\BObama\My Documents\foo"--runtime-deps-list-file: Save runtime dependencies for targets in file. --runtime-deps-list-file=<filename> Where <filename> is a text file consisting of the labels, one per line, of the targets for which runtime dependencies are desired. See "gn help runtime_deps" for a description of how runtime dependencies are computed.Runtime deps output file For each target requested, GN will write a separate runtime dependency file. The runtime dependency file will be in the output directory alongside the output file of the target, with a ".runtime_deps" extension. For example, if the target "//foo:bar" is listed in the input file, and that target produces an output file "bar.so", GN will create a file "bar.so.runtime_deps" in the build directory. If a source set, action, copy, or group is listed, the runtime deps file will correspond to the .stamp file corresponding to that target. This is probably not useful; the use-case for this feature is generally executable targets. The runtime dependency file will list one file per line, with no escaping. The files will be relative to the root_build_dir. The first line of the file will be the main output file of the target itself (in the above example, "bar.so").--time: Outputs a summary of how long everything took. Hopefully self-explanatory.Examples gn gen out/Default --time--tracelog: Writes a Chrome-compatible trace log to the given file. The trace log will show file loads, executions, scripts, and writes. This allows performance analysis of the generation step. To view the trace, open Chrome and navigate to "chrome://tracing/", then press "Load" and specify the file you passed to this parameter.Examples gn gen out/Default --tracelog=mytrace.trace-v: Verbose logging. This will spew logging events to the console for debugging issues. Good luck!gn args <out_dir> [--list] [--short] [--args] See also "gn help buildargs" for a more high-level overview of how build arguments work.Usage gn args <out_dir> Open the arguments for the given build directory in an editor (as specified by the EDITOR environment variable). If the given build directory doesn't exist, it will be created and an empty args file will be opened in the editor. You would type something like this into that file: enable_doom_melon=false os="android" Note: you can edit the build args manually by editing the file "args.gn" in the build directory and then running "gn gen <out_dir>". gn args <out_dir> --list[=<exact_arg>] [--short] Lists all build arguments available in the current configuration, or, if an exact_arg is specified for the list flag, just that one build argument. The output will list the declaration location, default value, and comment preceeding the declaration. If --short is specified, only the names and values will be printed. If the out_dir is specified, the build configuration will be taken from that build directory. The reason this is needed is that the definition of some arguments is dependent on the build configuration, so setting some values might add, remove, or change the default values for other arguments. Specifying your exact configuration allows the proper arguments to be displayed. Instead of specifying the out_dir, you can also use the command-line flag to specify the build configuration: --args=<exact list of args to use>Examples gn args out/Debug Opens an editor with the args for out/Debug. gn args out/Debug --list --short Prints all arguments with their default values for the out/Debug build. gn args out/Debug --list=target_cpu Prints information about the "target_cpu" argument for the out/Debug build. gn args --list --args="os=\"android\" enable_doom_melon=true" Prints all arguments with the default values for a build with the given arguments set (which may affect the values of other arguments).gn check <out_dir> [<label_pattern>] [--force] "gn check" is the same thing as "gn gen" with the "--check" flag except that this command does not write out any build files. It's intended to be an easy way to manually trigger include file checking. The <label_pattern> can take exact labels or patterns that match more than one (although not general regular expressions). If specified, only those matching targets will be checked. See "gn help label_pattern" for details. The .gn file may specify a list of targets to be checked. Only these targets will be checked if no label_pattern is specified on the command line. Otherwise, the command-line list is used instead. See "gn help dotfile".Command-specific switches --force Ignores specifications of "check_includes = false" and checks all target's files that match the target label.Examples gn check out/Debug Check everything. gn check out/Default //foo:bar Check only the files in the //foo:bar target. gn check out/Default "//foo/* Check only the files in targets in the //foo directory tree.gn clean <out_dir> Deletes the contents of the output directory except for args.gn and creates a Ninja build environment sufficient to regenerate the build.gn desc <out_dir> [] [--blame] Displays information about a given labeled target for the given build. The build parameters will be taken for the build in the given <out_dir>.Possibilities for (If unspecified an overall summary will be displayed.) sources Source files. inputs Additional input dependencies. public Public header files. check_includes Whether "gn check" checks this target for include usage. allow_circular_includes_from Permit includes from these targets. visibility Prints which targets can depend on this one. testonly Whether this target may only be used in tests. configs Shows configs applied to the given target, sorted in the order they're specified. This includes both configs specified in the "configs" variable, as well as configs pushed onto this target via dependencies specifying "all" or "direct" dependent configs. deps Show immediate or recursive dependencies. See below for flags that control deps printing. public_configs all_dependent_configs Shows the labels of configs applied to targets that depend on this one (either directly or all of them). forward_dependent_configs_from Shows the labels of dependencies for which dependent configs will be pushed to targets depending on the current one. script args depfile Actions only. The script and related values. outputs Outputs for script and copy target types. defines [--blame] include_dirs [--blame] cflags [--blame] cflags_cc [--blame] cflags_cxx [--blame] ldflags [--blame] lib_dirs libs Shows the given values taken from the target and all configs applying. See "--blame" below. runtime_deps Compute all runtime deps for the given target. This is a computed list and does not correspond to any GN variable, unlike most other values here. The output is a list of file names relative to the build directory. See "gn help runtime_deps" for how this is computed. This also works with "--blame" to see the source of the dependency.Shared flags --blame Used with any value specified by a config, this will name the config that specified the value. This doesn't currently work for libs and lib_dirs because those are inherited and are more complicated to figure out the blame (patches welcome).Flags that control how deps are printed --all Collects all recursive dependencies and prints a sorted flat list. Also usable with --tree (see below). --as=(buildfile|label|output) How to print targets. buildfile Prints the build files where the given target was declared as file names. label (default) Prints the label of the target. output Prints the first output file for the target relative to the current directory. --testonly=(true|false) Restrict outputs to targets with the testonly flag set accordingly. When unspecified, the target's testonly flags are ignored. --tree Print a dependency tree. By default, duplicates will be elided with "..." but when --all and -tree are used together, no eliding will be performed. The "deps", "public_deps", and "data_deps" will all be included in the tree. Tree output can not be used with the filtering or output flags: --as, --type, --testonly. --type=(action|copy|executable|group|shared_library|source_set| static_library) Restrict outputs to targets matching the given type. If unspecified, no filtering will be performed.Note This command will show the full name of directories and source files, but when directories and source paths are written to the build file, they will be adjusted to be relative to the build directory. So the values for paths displayed by this command won't match (but should mean the same thing).Examples gn desc out/Debug //base:base Summarizes the given target. gn desc out/Foo :base_unittests deps --tree Shows a dependency tree of the "base_unittests" project in the current directory. gn desc out/Debug //base defines --blame Shows defines set for the //base:base target, annotated by where each one was set from.gn format [--dump-tree] [--in-place] [--stdin] BUILD.gn Formats .gn file to a standard format.Arguments --dry-run Does not change or output anything, but sets the process exit code based on whether output would be different than what's on disk. This is useful for presubmit/lint-type checks. - Exit code 0: successful format, matches on disk. - Exit code 1: general failure (parse error, etc.) - Exit code 2: successful format, but differs from on disk. --dump-tree For debugging only, dumps the parse tree. --in-place Instead of writing the formatted file to stdout, replace the input file with the formatted output. If no reformatting is required, the input file will not be touched, and nothing printed. --stdin Read input from stdin (and write to stdout). Not compatible with --in-place of course.Examples gn format //some/BUILD.gn gn format some\BUILD.gn gn format /abspath/some/BUILD.gn gn format --stdingn gen: Generate ninja files. gn gen <out_dir> Generates ninja files from the current tree and puts them in the given output directory. The output directory can be a source-repo-absolute path name such as: //out/foo Or it can be a directory relative to the current directory such as: out/foo See "gn help" for the common command-line switches.gn help Yo dawg, I heard you like help on your help so I put help on the help in the help.gn ls <out_dir> [<label_pattern>] [--all-toolchains] [--as=...] [--type=...] [--testonly=...] Lists all targets matching the given pattern for the given build directory. By default, only targets in the default toolchain will be matched unless a toolchain is explicitly supplied. If the label pattern is unspecified, list all targets. The label pattern is not a general regular expression (see "gn help label_pattern"). If you need more complex expressions, pipe the result through grep.Options --as=(buildfile|label|output) How to print targets. buildfile Prints the build files where the given target was declared as file names. label (default) Prints the label of the target. output Prints the first output file for the target relative to the current directory. --all-toolchains Matches all toolchains. When set, if the label pattern does not specify an explicit toolchain, labels from all toolchains will be matched. When unset, only targets in the default toolchain will be matched unless an explicit toolchain in the label is set. --testonly=(true|false) Restrict outputs to targets with the testonly flag set accordingly. When unspecified, the target's testonly flags are ignored. --type=(action|copy|executable|group|shared_library|source_set| static_library) Restrict outputs to targets matching the given type. If unspecified, no filtering will be performed.Examples gn ls out/Debug Lists all targets in the default toolchain. gn ls out/Debug "//base/*" Lists all targets in the directory base and all subdirectories. gn ls out/Debug "//base:*" Lists all targets defined in //base/BUILD.gn. gn ls out/Debug //base --as=output Lists the build output file for //base:base gn ls out/Debug --type=executable Lists all executables produced by the build. gn ls out/Debug "//base/*" --as=output | xargs ninja -C out/Debug Builds all targets in //base and all subdirectories. gn ls out/Debug //base --all-toolchains Lists all variants of the target //base:base (it may be referenced in multiple toolchains).gn path <out_dir> <target_one> <target_two> Finds paths of dependencies between two targets. Each unique path will be printed in one group, and groups will be separate by newlines. The two targets can appear in either order: paths will be found going in either direction. Each dependency will be annotated with its type. By default, only the first path encountered will be printed, which is not necessarily the shortest path.Options --all Prints all paths found rather than just the first one.Example gn path out/Default //base //tools/gngn refs <out_dir> (<label_pattern>|||@<response_file>)* [--all] [--all-toolchains] [--as=...] [--testonly=...] [--type=...] Finds reverse dependencies (which targets reference something). The input is a list containing: - Target label: The result will be which targets depend on it. - Config label: The result will be which targets list the given config in its "configs" or "public_configs" list. - Label pattern: The result will be which targets depend on any target matching the given pattern. Patterns will not match configs. These are not general regular expressions, see "gn help label_pattern" for details. - File name: The result will be which targets list the given file in its "inputs", "sources", "public", "data", or "outputs". Any input that does not contain wildcards and does not match a target or a config will be treated as a file. - Response file: If the input starts with an "@", it will be interpreted as a path to a file containing a list of labels or file names, one per line. This allows us to handle long lists of inputs without worrying about command line limits.Options --all When used without --tree, will recurse and display all unique dependencies of the given targets. For example, if the input is a target, this will output all targets that depend directly or indirectly on the input. If the input is a file, this will output all targets that depend directly or indirectly on that file. When used with --tree, turns off eliding to show a complete tree. --all-toolchains Normally only inputs in the default toolchain will be included. This switch will turn on matching all toolchains. For example, a file is in a target might be compiled twice: once in the default toolchain and once in a secondary one. Without this flag, only the default toolchain one will be matched and printed (potentially with its recursive dependencies, depending on the other options). With this flag, both will be printed (potentially with both of their recursive dependencies). --as=(buildfile|label|output) How to print targets. buildfile Prints the build files where the given target was declared as file names. label (default) Prints the label of the target. output Prints the first output file for the target relative to the current directory. -q Quiet. If nothing matches, don't print any output. Without this option, if there are no matches there will be an informational message printed which might interfere with scripts processing the output. --testonly=(true|false) Restrict outputs to targets with the testonly flag set accordingly. When unspecified, the target's testonly flags are ignored. --tree Outputs a reverse dependency tree from the given target. Duplicates will be elided. Combine with --all to see a full dependency tree. Tree output can not be used with the filtering or output flags: --as, --type, --testonly. --type=(action|copy|executable|group|shared_library|source_set| static_library) Restrict outputs to targets matching the given type. If unspecified, no filtering will be performed.Examples (target input) gn refs out/Debug //tools/gn:gn Find all targets depending on the given exact target name. gn refs out/Debug //base:i18n --as=buildfiles | xargs gvim Edit all .gn files containing references to //base:i18n gn refs out/Debug //base --all List all targets depending directly or indirectly on //base:base. gn refs out/Debug "//base/*" List all targets depending directly on any target in //base or its subdirectories. gn refs out/Debug "//base:*" List all targets depending directly on any target in //base/BUILD.gn. gn refs out/Debug //base --tree Print a reverse dependency tree of //base:baseExamples (file input) gn refs out/Debug //base/macros.h Print target(s) listing //base/macros.h as a source. gn refs out/Debug //base/macros.h --tree Display a reverse dependency tree to get to the given file. This will show how dependencies will reference that file. gn refs out/Debug //base/macros.h //base/at_exit.h --all Display all unique targets with some dependency path to a target containing either of the given files as a source. gn refs out/Debug //base/macros.h --testonly=true --type=executable --all --as=output Display the executable file names of all test executables potentially affected by a change to the given file.action: Declare a target that runs a script a single time. This target type allows you to run a script a single time to produce or more output files. If you want to run a script once for each of a set of input files, see "gn help action_foreach".Inputs In an action the "sources" and "inputs" are treated the same: they're both input dependencies on script execution with no special handling. If you want to pass the sources to your script, you must do so explicitly by including them in the "args". Note also that this means there is no special handling of paths since GN doesn't know which of the args are paths and not. You will want to use rebase_path() to convert paths to be relative to the root_build_dir. You can dynamically write input dependencies (for incremental rebuilds if an input file changes) by writing a depfile when the script is run (see "gn help depfile"). This is more flexible than "inputs". It is recommended you put inputs to your script in the "sources" variable, and stuff like other Python files required to run your script in the "inputs" variable. The "deps" and "public_deps" for an action will always be completed before any part of the action is run so it can depend on the output of previous steps. The "data_deps" will be built if the action is built, but may not have completed before all steps of the action are started. This can give additional parallelism in the build for runtime-only dependencies.Outputs You should specify files created by your script by specifying them in the "outputs". The script will be executed with the given arguments with the current directory being that of the root build directory. If you pass files to your script, see "gn help rebase_path" for how to convert file names to be relative to the build directory (file names in the sources, outputs, and inputs will be all treated as relative to the current build file and converted as needed automatically).File name handling All output files must be inside the output directory of the build. You would generally use |$target_out_dir| or |$target_gen_dir| to reference the output or generated intermediate file directories, respectively.Variables args, data, data_deps, depfile, deps, outputs*, script*, inputs, sources * = requiredExample action("run_this_guy_once") { script = "doprocessing.py" sources = [ "my_configuration.txt" ] outputs = [ "$target_gen_dir/insightful_output.txt" ] # Our script imports this Python file so we want to rebuild if it # changes. inputs = [ "helper_library.py" ] # Note that we have to manually pass the sources to our script if # the script needs them as inputs. args = [ "--out", rebase_path(target_gen_dir, root_build_dir) ] + rebase_path(sources, root_build_dir) }action_foreach: Declare a target that runs a script over a set of files. This target type allows you to run a script once-per-file over a set of sources. If you want to run a script once that takes many files as input, see "gn help action".Inputs The script will be run once per file in the "sources" variable. The "outputs" variable should specify one or more files with a source expansion pattern in it (see "gn help source_expansion"). The output file(s) for each script invocation should be unique. Normally you use "{{source_name_part}}" in each output file. If your script takes additional data as input, such as a shared configuration file or a Python module it uses, those files should be listed in the "inputs" variable. These files are treated as dependencies of each script invocation. You can dynamically write input dependencies (for incremental rebuilds if an input file changes) by writing a depfile when the script is run (see "gn help depfile"). This is more flexible than "inputs". The "deps" and "public_deps" for an action will always be completed before any part of the action is run so it can depend on the output of previous steps. The "data_deps" will be built if the action is built, but may not have completed before all steps of the action are started. This can give additional parallelism in the build for runtime-only dependencies.Outputs The script will be executed with the given arguments with the current directory being that of the root build directory. If you pass files to your script, see "gn help rebase_path" for how to convert file names to be relative to the build directory (file names in the sources, outputs, and inputs will be all treated as relative to the current build file and converted as needed automatically).File name handling All output files must be inside the output directory of the build. You would generally use |$target_out_dir| or |$target_gen_dir| to reference the output or generated intermediate file directories, respectively.Variables args, data, data_deps, depfile, deps, outputs*, script*, inputs, sources* * = requiredExample # Runs the script over each IDL file. The IDL script will generate # both a .cc and a .h file for each input. action_foreach("my_idl") { script = "idl_processor.py" sources = [ "foo.idl", "bar.idl" ] # Our script reads this file each time, so we need to list is as a # dependency so we can rebuild if it changes. inputs = [ "my_configuration.txt" ] # Transformation from source file name to output file names. outputs = [ "$target_gen_dir/{{source_name_part}}.h", "$target_gen_dir/{{source_name_part}}.cc" ] # Note that since "args" is opaque to GN, if you specify paths # here, you will need to convert it to be relative to the build # directory using "rebase_path()". args = [ "{{source}}", "-o", rebase_path(relative_target_gen_dir, root_build_dir) + "/{{source_name_part}}.h" ] }assert: Assert an expression is true at generation time. assert(<condition> [, <error string>]) If the condition is false, the build will fail with an error. If the optional second argument is provided, that string will be printed with the error message.Examples: assert(is_win) assert(defined(sources), "Sources must be defined")config: Defines a configuration object. Configuration objects can be applied to targets and specify sets of compiler flags, includes, defines, etc. They provide a way to conveniently group sets of this configuration information. A config is referenced by its label just like a target. The values in a config are additive only. If you want to remove a flag you need to remove the corresponding config that sets it. The final set of flags, defines, etc. for a target is generated in this order: 1. The values specified directly on the target (rather than using a config. 2. The configs specified in the target's "configs" list, in order. 3. Public_configs from a breadth-first traversal of the dependency tree in the order that the targets appear in "deps". 4. All dependent configs from a breadth-first traversal of the dependency tree in the order that the targets appear in "deps".Variables valid in a config definition: Flags: cflags, cflags_c, cflags_cc, cflags_objc, cflags_objcc, defines, include_dirs, ldflags, lib_dirs, libs precompiled_header, precompiled_sourceVariables on a target used to apply configs: all_dependent_configs, configs, public_configs, forward_dependent_configs_fromExample: config("myconfig") { includes = [ "include/common" ] defines = [ "ENABLE_DOOM_MELON" ] } executable("mything") { configs = [ ":myconfig" ] }copy: Declare a target that copies files.File name handling All output files must be inside the output directory of the build. You would generally use |$target_out_dir| or |$target_gen_dir| to reference the output or generated intermediate file directories, respectively. Both "sources" and "outputs" must be specified. Sources can as many files as you want, but there can only be one item in the outputs list (plural is used for the name for consistency with other target types). If there is more than one source file, your output name should specify a mapping from each source files to output file names using source expansion (see "gn help source_expansion"). The placeholders will will look like "{{source_name_part}}", for example.Examples # Write a rule that copies a checked-in DLL to the output directory. copy("mydll") { sources = [ "mydll.dll" ] outputs = [ "$target_out_dir/mydll.dll" ] } # Write a rule to copy several files to the target generated files # directory. copy("myfiles") { sources = [ "data1.dat", "data2.dat", "data3.dat" ] # Use source expansion to generate output files with the # corresponding file names in the gen dir. This will just copy each # file. outputs = [ "$target_gen_dir/{{source_file_part}}" ] }declare_args: Declare build arguments. Introduces the given arguments into the current scope. If they are not specified on the command line or in a toolchain's arguments, the default values given in the declare_args block will be used. However, these defaults will not override command-line values. See also "gn help buildargs" for an overview.Example: declare_args() { enable_teleporter = true enable_doom_melon = false } If you want to override the (default disabled) Doom Melon: gn --args="enable_doom_melon=true enable_teleporter=false" This also sets the teleporter, but it's already defaulted to on so it will have no effect.defined: Returns whether an identifier is defined. Returns true if the given argument is defined. This is most useful in templates to assert that the caller set things up properly. You can pass an identifier: defined(foo) which will return true or false depending on whether foo is defined in the current scope. You can also check a named scope: defined(foo.bar) which will return true or false depending on whether bar is defined in the named scope foo. It will throw an error if foo is not defined or is not a scope.Example: template("mytemplate") { # To help users call this template properly... assert(defined(invoker.sources), "Sources must be defined") # If we want to accept an optional "values" argument, we don't # want to dereference something that may not be defined. if (defined(invoker.values)) { values = invoker.values } else { values = "some default value" } }exec_script: Synchronously run a script and return the output. exec_script(filename, arguments = [], input_conversion = "", file_dependencies = []) Runs the given script, returning the stdout of the script. The build generation will fail if the script does not exist or returns a nonzero exit code. The current directory when executing the script will be the root build directory. If you are passing file names, you will want to use the rebase_path() function to make file names relative to this path (see "gn help rebase_path").Arguments: filename: File name of python script to execute. Non-absolute names will be treated as relative to the current build file. arguments: A list of strings to be passed to the script as arguments. May be unspecified or the empty list which means no arguments. input_conversion: Controls how the file is read and parsed. See "gn help input_conversion". If unspecified, defaults to the empty string which causes the script result to be discarded. exec script will return None. dependencies: (Optional) A list of files that this script reads or otherwise depends on. These dependencies will be added to the build result such that if any of them change, the build will be regenerated and the script will be re-run. The script itself will be an implicit dependency so you do not need to list it.Example: all_lines = exec_script( "myscript.py", [some_input], "list lines", [ rebase_path("data_file.txt", root_build_dir) ]) # This example just calls the script with no arguments and discards # the result. exec_script("//foo/bar/myscript.py")executable: Declare an executable target.Variables Flags: cflags, cflags_c, cflags_cc, cflags_objc, cflags_objcc, defines, include_dirs, ldflags, lib_dirs, libs precompiled_header, precompiled_source Deps: data_deps, deps, forward_dependent_configs_from, public_deps Dependent configs: all_dependent_configs, public_configs General: check_includes, configs, data, inputs, output_name, output_extension, public, sources, testonly, visibilityforeach: Iterate over a list. foreach(<loop_var>, <list>) { <loop contents> } Executes the loop contents block over each item in the list, assigning the loop_var to each item in sequence. The block does not introduce a new scope, so that variable assignments inside the loop will be visible once the loop terminates. The loop variable will temporarily shadow any existing variables with the same name for the duration of the loop. After the loop terminates the loop variable will no longer be in scope, and the previous value (if any) will be restored.Example mylist = [ "a", "b", "c" ] foreach(i, mylist) { print(i) } Prints: a b cget_label_info: Get an attribute from a target's label. get_label_info(target_label, what) Given the label of a target, returns some attribute of that target. The target need not have been previously defined in the same file, since none of the attributes depend on the actual target definition, only the label itself. See also "gn help get_target_outputs".Possible values for the “what” parameter "name" The short name of the target. This will match the value of the "target_name" variable inside that target's declaration. For the label "//foo/bar:baz" this will return "baz". "dir" The directory containing the target's definition, with no slash at the end. For the label "//foo/bar:baz" this will return "//foo/bar". "target_gen_dir" The generated file directory for the target. This will match the value of the "target_gen_dir" variable when inside that target's declaration. "root_gen_dir" The root of the generated file tree for the target. This will match the value of the "root_gen_dir" variable when inside that target's declaration. "target_out_dir The output directory for the target. This will match the value of the "target_out_dir" variable when inside that target's declaration. "root_out_dir" The root of the output file tree for the target. This will match the value of the "root_gen_dir" variable when inside that target's declaration. "label_no_toolchain" The fully qualified version of this label, not including the toolchain. For the input ":bar" it might return "//foo:bar". "label_with_toolchain" The fully qualified version of this label, including the toolchain. For the input ":bar" it might return "//foo:bar(//toolchain:x64)". "toolchain" The label of the toolchain. This will match the value of the "current_toolchain" variable when inside that target's declaration.Examples get_label_info(":foo", "name") # Returns string "foo". get_label_info("//foo/bar:baz", "gen_dir") # Returns string "//out/Debug/gen/foo/bar".get_path_info: Extract parts of a file or directory name. get_path_info(input, what) The first argument is either a string representing a file or directory name, or a list of such strings. If the input is a list the return value will be a list containing the result of applying the rule to each item in the input.Possible values for the “what” parameter "file" The substring after the last slash in the path, including the name and extension. If the input ends in a slash, the empty string will be returned. "foo/bar.txt" => "bar.txt" "bar.txt" => "bar.txt" "foo/" => "" "" => "" "name" The substring of the file name not including the extension. "foo/bar.txt" => "bar" "foo/bar" => "bar" "foo/" => "" "extension" The substring following the last period following the last slash, or the empty string if not found. The period is not included. "foo/bar.txt" => "txt" "foo/bar" => "" "dir" The directory portion of the name, not including the slash. "foo/bar.txt" => "foo" "//foo/bar" => "//foo" "foo" => "." The result will never end in a slash, so if the resulting is empty, the system ("/") or source ("//") roots, a "." will be appended such that it is always legal to append a slash and a filename and get a valid path. "out_dir" The output file directory corresponding to the path of the given file, not including a trailing slash. "//foo/bar/baz.txt" => "//out/Default/obj/foo/bar" "gen_dir" The generated file directory corresponding to the path of the given file, not including a trailing slash. "//foo/bar/baz.txt" => "//out/Default/gen/foo/bar" "abspath" The full absolute path name to the file or directory. It will be resolved relative to the currebt directory, and then the source- absolute version will be returned. If the input is system- absolute, the same input will be returned. "foo/bar.txt" => "//mydir/foo/bar.txt" "foo/" => "//mydir/foo/" "//foo/bar" => "//foo/bar" (already absolute) "/usr/include" => "/usr/include" (already absolute) If you want to make the path relative to another directory, or to be system-absolute, see rebase_path().Examples sources = [ "foo.cc", "foo.h" ] result = get_path_info(source, "abspath") # result will be [ "//mydir/foo.cc", "//mydir/foo.h" ] result = get_path_info("//foo/bar/baz.cc", "dir") # result will be "//foo/bar" # Extract the source-absolute directory name, result = get_path_info(get_path_info(path, "dir"), "abspath")get_target_outputs: [file list] Get the list of outputs from a target. get_target_outputs(target_label) Returns a list of output files for the named target. The named target must have been previously defined in the current file before this function is called (it can't reference targets in other files because there isn't a defined execution order, and it obviously can't reference targets that are defined after the function call). Only copy and action targets are supported. The outputs from binary targets will depend on the toolchain definition which won't necessarily have been loaded by the time a given line of code has run, and source sets and groups have no useful output file.Return value The names in the resulting list will be absolute file paths (normally like "//out/Debug/bar.exe", depending on the build directory). action targets: this will just return the files specified in the "outputs" variable of the target. action_foreach targets: this will return the result of applying the output template to the sources (see "gn help source_expansion"). This will be the same result (though with guaranteed absolute file paths), as process_file_template will return for those inputs (see "gn help process_file_template"). binary targets (executables, libraries): this will return a list of the resulting binary file(s). The "main output" (the actual binary or library) will always be the 0th element in the result. Depending on the platform and output type, there may be other output files as well (like import libraries) which will follow. source sets and groups: this will return a list containing the path of the "stamp" file that Ninja will produce once all outputs are generated. This probably isn't very useful.Example # Say this action generates a bunch of C source files. action_foreach("my_action") { sources = [ ... ] outputs = [ ... ] } # Compile the resulting source files into a source set. source_set("my_lib") { sources = get_target_outputs(":my_action") }getenv: Get an environment variable. value = getenv(env_var_name) Returns the value of the given enironment variable. If the value is not found, it will try to look up the variable with the "opposite" case (based on the case of the first letter of the variable), but is otherwise case-sensitive. If the environment variable is not found, the empty string will be returned. Note: it might be nice to extend this if we had the concept of "none" in the language to indicate lookup failure.Example: home_dir = getenv("HOME")group: Declare a named group of targets. This target type allows you to create meta-targets that just collect a set of dependencies into one named target. Groups can additionally specify configs that apply to their dependents. Depending on a group is exactly like depending directly on that group's deps. Direct dependent configs will get automatically forwarded through the group so you shouldn't need to use "forward_dependent_configs_from.Variables Deps: data_deps, deps, forward_dependent_configs_from, public_deps Dependent configs: all_dependent_configs, public_configsExample group("all") { deps = [ "//project:runner", "//project:unit_tests", ] }import: Import a file into the current scope. The import command loads the rules and variables resulting from executing the given file into the current scope. By convention, imported files are named with a .gni extension. An import is different than a C++ "include". The imported file is executed in a standalone environment from the caller of the import command. The results of this execution are cached for other files that import the same .gni file. Note that you can not import a BUILD.gn file that's otherwise used in the build. Files must either be imported or implicitly loaded as a result of deps rules, but not both. The imported file's scope will be merged with the scope at the point import was called. If there is a conflict (both the current scope and the imported file define some variable or rule with the same name but different value), a runtime error will be thrown. Therefore, it's good practice to minimize the stuff that an imported file defines. Variables and templates beginning with an underscore '_' are considered private and will not be imported. Imported files can use such variables for internal computation without affecting other files.Examples: import("//build/rules/idl_compilation_rule.gni") # Looks in the current directory. import("my_vars.gni")print: Prints to the console. Prints all arguments to the console separated by spaces. A newline is automatically appended to the end. This function is intended for debugging. Note that build files are run in parallel so you may get interleaved prints. A buildfile may also be executed more than once in parallel in the context of different toolchains so the prints from one file may be duplicated or interleaved with itself.Examples: print("Hello world") print(sources, deps)process_file_template: Do template expansion over a list of files. process_file_template(source_list, template) process_file_template applies a template list to a source file list, returning the result of applying each template to each source. This is typically used for computing output file names from input files. In most cases, get_target_outputs() will give the same result with shorter, more maintainable code. This function should only be used when that function can't be used (like there's no target or the target is defined in another build file).Arguments: The source_list is a list of file names. The template can be a string or a list. If it is a list, multiple output strings are generated for each input. The template should contain source expansions to which each name in the source list is applied. See "gn help source_expansion".Example: sources = [ "foo.idl", "bar.idl", ] myoutputs = process_file_template( sources, [ "$target_gen_dir/{{source_name_part}}.cc", "$target_gen_dir/{{source_name_part}}.h" ]) The result in this case will be: [ "//out/Debug/foo.cc" "//out/Debug/foo.h" "//out/Debug/bar.cc" "//out/Debug/bar.h" ]read_file: Read a file into a variable. read_file(filename, input_conversion) Whitespace will be trimmed from the end of the file. Throws an error if the file can not be opened.Arguments: filename Filename to read, relative to the build file. input_conversion Controls how the file is read and parsed. See "gn help input_conversion".Example lines = read_file("foo.txt", "list lines")rebase_path: Rebase a file or directory to another location. converted = rebase_path(input, new_base = "", current_base = ".") Takes a string argument representing a file name, or a list of such strings and converts it/them to be relative to a different base directory. When invoking the compiler or scripts, GN will automatically convert sources and include directories to be relative to the build directory. However, if you're passing files directly in the "args" array or doing other manual manipulations where GN doesn't know something is a file name, you will need to convert paths to be relative to what your tool is expecting. The common case is to use this to convert paths relative to the current directory to be relative to the build directory (which will be the current directory when executing scripts). If you want to convert a file path to be source-absolute (that is, beginning with a double slash like "//foo/bar"), you should use the get_path_info() function. This function won't work because it will always make relative paths, and it needs to support making paths relative to the source root, so can't also generate source-absolute paths without more special-cases.Arguments: input A string or list of strings representing file or directory names These can be relative paths ("foo/bar.txt"), system absolute paths ("/foo/bar.txt"), or source absolute paths ("//foo/bar.txt"). new_base The directory to convert the paths to be relative to. This can be an absolute path or a relative path (which will be treated as being relative to the current BUILD-file's directory). As a special case, if new_base is the empty string (the default), all paths will be converted to system-absolute native style paths with system path separators. This is useful for invoking external programs. current_base Directory representing the base for relative paths in the input. If this is not an absolute path, it will be treated as being relative to the current build file. Use "." (the default) to convert paths from the current BUILD-file's directory.Return value The return value will be the same type as the input value (either a string or a list of strings). All relative and source-absolute file names will be converted to be relative to the requested output System-absolute paths will be unchanged.Example # Convert a file in the current directory to be relative to the build # directory (the current dir when executing compilers and scripts). foo = rebase_path("myfile.txt", root_build_dir) # might produce "../../project/myfile.txt". # Convert a file to be system absolute: foo = rebase_path("myfile.txt") # Might produce "D:\source\project\myfile.txt" on Windows or # "/home/you/source/project/myfile.txt" on Linux. # Typical usage for converting to the build directory for a script. action("myscript") { # Don't convert sources, GN will automatically convert these to be # relative to the build directory when it constructs the command # line for your script. sources = [ "foo.txt", "bar.txt" ] # Extra file args passed manually need to be explicitly converted # to be relative to the build directory: args = [ "--data", rebase_path("//mything/data/input.dat", root_build_dir), "--rel", rebase_path("relative_path.txt", root_build_dir) ] + rebase_path(sources, root_build_dir) }set_default_toolchain: Sets the default toolchain name. set_default_toolchain(toolchain_label) The given label should identify a toolchain definition (see "help toolchain"). This toolchain will be used for all targets unless otherwise specified. This function is only valid to call during the processing of the build configuration file. Since the build configuration file is processed separately for each toolchain, this function will be a no-op when called under any non-default toolchains. For example, the default toolchain should be appropriate for the current environment. If the current environment is 32-bit and somebody references a target with a 64-bit toolchain, we wouldn't want processing of the build config file for the 64-bit toolchain to reset the default toolchain to 64-bit, we want to keep it 32-bits.Argument: toolchain_label Toolchain name.Example: set_default_toolchain("//build/config/win:vs32")set_defaults: Set default values for a target type. set_defaults(<target_type_name>) { <values...> } Sets the default values for a given target type. Whenever target_type_name is seen in the future, the values specified in set_default's block will be copied into the current scope. When the target type is used, the variable copying is very strict. If a variable with that name is already in scope, the build will fail with an error. set_defaults can be used for built-in target types ("executable", "shared_library", etc.) and custom ones defined via the "template" command.Example: set_defaults("static_library") { configs = [ "//tools/mything:settings" ] } static_library("mylib") # The configs will be auto-populated as above. You can remove it if # you don't want the default for a particular default: configs -= "//tools/mything:settings" }set_sources_assignment_filter: Set a pattern to filter source files. The sources assignment filter is a list of patterns that remove files from the list implicitly whenever the "sources" variable is assigned to. This is intended to be used to globally filter out files with platform-specific naming schemes when they don't apply, for example, you may want to filter out all "*_win.cc" files on non- Windows platforms. Typically this will be called once in the master build config script to set up the filter for the current platform. Subsequent calls will overwrite the previous values. If you want to bypass the filter and add a file even if it might be filtered out, call set_sources_assignment_filter([]) to clear the list of filters. This will apply until the current scope exitsHow to use patterns File patterns are VERY limited regular expressions. They must match the entire input string to be counted as a match. In regular expression parlance, there is an implicit "^...$" surrounding your input. If you want to match a substring, you need to use wildcards at the beginning and end. There are only two special tokens understood by the pattern matcher. Everything else is a literal. * Matches zero or more of any character. It does not depend on the preceding character (in regular expression parlance it is equivalent to ".*"). \b Matches a path boundary. This will match the beginning or end of a string, or a slash.Pattern examples "*asdf*" Matches a string containing "asdf" anywhere. "asdf" Matches only the exact string "asdf". "*.cc" Matches strings ending in the literal ".cc". "\bwin/*" Matches "win/foo" and "foo/win/bar.cc" but not "iwin/foo".Sources assignment example # Filter out all _win files. set_sources_assignment_filter([ "*_win.cc", "*_win.h" ]) sources = [ "a.cc", "b_win.cc" ] print(sources) # Will print [ "a.cc" ]. b_win one was filtered out.shared_library: Declare a shared library target. A shared library will be specified on the linker line for targets listing the shared library in its "deps". If you don't want this (say you dynamically load the library at runtime), then you should depend on the shared library via "data_deps" instead.Variables Flags: cflags, cflags_c, cflags_cc, cflags_objc, cflags_objcc, defines, include_dirs, ldflags, lib_dirs, libs precompiled_header, precompiled_source Deps: data_deps, deps, forward_dependent_configs_from, public_deps Dependent configs: all_dependent_configs, public_configs General: check_includes, configs, data, inputs, output_name, output_extension, public, sources, testonly, visibilitysource_set: Declare a source set target. A source set is a collection of sources that get compiled, but are not linked to produce any kind of library. Instead, the resulting object files are implicitly added to the linker line of all targets that depend on the source set. In most cases, a source set will behave like a static library, except no actual library file will be produced. This will make the build go a little faster by skipping creation of a large static library, while maintaining the organizational benefits of focused build targets. The main difference between a source set and a static library is around handling of exported symbols. Most linkers assume declaring a function exported means exported from the static library. The linker can then do dead code elimination to delete code not reachable from exported functions. A source set will not do this code elimination since there is no link step. This allows you to link many sources sets into a shared library and have the "exported symbol" notation indicate "export from the final shared library and not from the intermediate targets." There is no way to express this concept when linking multiple static libraries into a shared library.Variables Flags: cflags, cflags_c, cflags_cc, cflags_objc, cflags_objcc, defines, include_dirs, ldflags, lib_dirs, libs precompiled_header, precompiled_source Deps: data_deps, deps, forward_dependent_configs_from, public_deps Dependent configs: all_dependent_configs, public_configs General: check_includes, configs, data, inputs, output_name, output_extension, public, sources, testonly, visibilitystatic_library: Declare a static library target. Make a ".a" / ".lib" file. If you only need the static library for intermediate results in the build, you should consider a source_set instead since it will skip the (potentially slow) step of creating the intermediate library file.Variables Flags: cflags, cflags_c, cflags_cc, cflags_objc, cflags_objcc, defines, include_dirs, ldflags, lib_dirs, libs precompiled_header, precompiled_source Deps: data_deps, deps, forward_dependent_configs_from, public_deps Dependent configs: all_dependent_configs, public_configs General: check_includes, configs, data, inputs, output_name, output_extension, public, sources, testonly, visibilitytemplate: Define a template rule. A template defines a custom name that acts like a function. It provides a way to add to the built-in target types. The template() function is used to declare a template. To invoke the template, just use the name of the template like any other target type. Often you will want to declare your template in a special file that other files will import (see "gn help import") so your template rule can be shared across build files.More details: When you call template() it creates a closure around all variables currently in scope with the code in the template block. When the template is invoked, the closure will be executed. When the template is invoked, the code in the caller is executed and passed to the template code as an implicit "invoker" variable. The template uses this to read state out of the invoking code. One thing explicitly excluded from the closure is the "current directory" against which relative file names are resolved. The current directory will be that of the invoking code, since typically that code specifies the file names. This means all files internal to the template should use absolute names.Target naming: Your template should almost always define a built-in target with the name the template invoker specified. For example, if you have an IDL template and somebody does: idl("foo") {... you will normally want this to expand to something defining a source_set or static_library named "foo" (among other things you may need). This way, when another target specifies a dependency on "foo", the static_library or source_set will be linked. It is also important that any other targets your template expands to have globally unique names, or you will get collisions. Access the invoking name in your template via the implicit "target_name" variable. This should also be the basis of how other targets that a template expands to to ensure uniquness. A typical example would be a template that defines an action to generate some source files, and a source_set to compile that source. Your template would name the source_set "target_name" because that's what you want external targets to depend on to link your code. And you would name the action something like "${target_name}_action" to make it unique. The source set would have a dependency on the action to make it run.Example of defining a template: template("my_idl") { # Be nice and help callers debug problems by checking that the # variables the template requires are defined. This gives a nice # message rather than giving the user an error about an # undefined variable in the file defining the template # # You can also use defined() to give default values to variables # unspecified by the invoker. assert(defined(invoker.sources), "Need sources in $target_name listing the idl files.") # Name of the intermediate target that does the code gen. This must # incorporate the target name so it's unique across template # instantiations. code_gen_target_name = target_name + "_code_gen" # Intermediate target to convert IDL to C source. Note that the name # is based on the name the invoker of the template specified. This # way, each time the template is invoked we get a unique # intermediate action name (since all target names are in the global # scope). action_foreach(code_gen_target_name) { # Access the scope defined by the invoker via the implicit # "invoker" variable. sources = invoker.sources # Note that we need an absolute path for our script file name. # The current directory when executing this code will be that of # the invoker (this is why we can use the "sources" directly # above without having to rebase all of the paths). But if we need # to reference a script relative to the template file, we'll need # to use an absolute path instead. script = "//tools/idl/idl_code_generator.py" # Tell GN how to expand output names given the sources. # See "gn help source_expansion" for more. outputs = [ "$target_gen_dir/{{source_name_part}}.cc", "$target_gen_dir/{{source_name_part}}.h" ] } # Name the source set the same as the template invocation so # instancing this template produces something that other targets # can link to in their deps. source_set(target_name) { # Generates the list of sources, we get these from the # action_foreach above. sources = get_target_outputs(":$code_gen_target_name") # This target depends on the files produced by the above code gen # target. deps = [ ":$code_gen_target_name" ] } }Example of invoking the resulting template: # This calls the template code above, defining target_name to be # "foo_idl_files" and "invoker" to be the set of stuff defined in # the curly brackets. my_idl("foo_idl_files") { # Goes into the template as "invoker.sources". sources = [ "foo.idl", "bar.idl" ] } # Here is a target that depends on our template. executable("my_exe") { # Depend on the name we gave the template call above. Internally, # this will produce a dependency from executable to the source_set # inside the template (since it has this name), which will in turn # depend on the code gen action. deps = [ ":foo_idl_files" ] }tool: Specify arguments to a toolchain tool.Usage: tool(<tool type>) { <tool variables...> }Tool types Compiler tools: "cc": C compiler "cxx": C++ compiler "objc": Objective C compiler "objcxx": Objective C++ compiler "rc": Resource compiler (Windows .rc files) "asm": Assembler Linker tools: "alink": Linker for static libraries (archives) "solink": Linker for shared libraries "link": Linker for executables Other tools: "stamp": Tool for creating stamp files "copy": Tool to copy files.Tool variables command [string with substitutions] Valid for: all tools (required) The command to run. default_output_extension [string] Valid for: linker tools Extension for the main output of a linkable tool. It includes the leading dot. This will be the default value for the {{output_extension}} expansion (discussed below) but will be overridden by by the "output extension" variable in a target, if one is specified. Empty string means no extension. GN doesn't actually do anything with this extension other than pass it along, potentially with target-specific overrides. One would typically use the {{output_extension}} value in the "outputs" to read this value. Example: default_output_extension = ".exe" depfile [string] Valid for: compiler tools (optional) If the tool can write ".d" files, this specifies the name of the resulting file. These files are used to list header file dependencies (or other implicit input dependencies) that are discovered at build time. See also "depsformat". Example: depfile = "{{output}}.d" depsformat [string] Valid for: compiler tools (when depfile is specified) Format for the deps outputs. This is either "gcc" or "msvc". See the ninja documentation for "deps" for more information. Example: depsformat = "gcc" description [string with substitutions, optional] Valid for: all tools What to print when the command is run. Example: description = "Compiling {{source}}" lib_switch [string, optional, link tools only] lib_dir_switch [string, optional, link tools only] Valid for: Linker tools except "alink" These strings will be prepended to the libraries and library search directories, respectively, because linkers differ on how specify them. If you specified: lib_switch = "-l" lib_dir_switch = "-L" then the "{{libs}}" expansion for [ "freetype", "expat"] would be "-lfreetype -lexpat". outputs [list of strings with substitutions] Valid for: Linker and compiler tools (required) An array of names for the output files the tool produces. These are relative to the build output directory. There must always be at least one output file. There can be more than one output (a linker might produce a library and an import library, for example). This array just declares to GN what files the tool will produce. It is your responsibility to specify the tool command that actually produces these files. If you specify more than one output for shared library links, you should consider setting link_output and depend_output. Otherwise, the first entry in the outputs list should always be the main output which will be linked to. Example for a compiler tool that produces .obj files: outputs = [ "{{source_out_dir}}/{{source_name_part}}.obj" ] Example for a linker tool that produces a .dll and a .lib. The use of {{output_extension}} rather than hardcoding ".dll" allows the extension of the library to be overridden on a target-by-target basis, but in this example, it always produces a ".lib" import library: outputs = [ "{{root_out_dir}}/{{target_output_name}}{{output_extension}}", "{{root_out_dir}}/{{target_output_name}}.lib", ] link_output [string with substitutions] depend_output [string with substitutions] Valid for: "solink" only (optional) These two files specify whch of the outputs from the solink tool should be used for linking and dependency tracking. These should match entries in the "outputs". If unspecified, the first item in the "outputs" array will be used for both. See "Separate linking and dependencies for shared libraries" below for more. On Windows, where the tools produce a .dll shared library and a .lib import library, you will want both of these to be the import library. On Linux, if you're not doing the separate linking/dependency optimization, both of these should be the .so output. output_prefix [string] Valid for: Linker tools (optional) Prefix to use for the output name. Defaults to empty. This prefix will be prepended to the name of the target (or the output_name if one is manually specified for it) if the prefix is not already there. The result will show up in the {{output_name}} substitution pattern. This is typically used to prepend "lib" to libraries on Posix systems: output_prefix = "lib" precompiled_header_type [string] Valid for: "cc", "cxx", "objc", "objcxx" Type of precompiled headers. If undefined or the empty string, precompiled headers will not be used for this tool. Otherwise use "msvc" which is the only currently supported value. For precompiled headers to be used for a given target, the target (or a config applied to it) must also specify a "precompiled_header" and, for "msvc"-style headers, a "precompiled_source" value. See "gn help precompiled_header" for more. restat [boolean] Valid for: all tools (optional, defaults to false) Requests that Ninja check the file timestamp after this tool has run to determine if anything changed. Set this if your tool has the ability to skip writing output if the output file has not changed. Normally, Ninja will assume that when a tool runs the output be new and downstream dependents must be rebuild. When this is set to trye, Ninja can skip rebuilding downstream dependents for input changes that don't actually affect the output. Example: restat = true rspfile [string with substitutions] Valid for: all tools (optional) Name of the response file. If empty, no response file will be used. See "rspfile_content". rspfile_content [string with substitutions] Valid for: all tools (required when "rspfile" is specified) The contents to be written to the response file. This may include all or part of the command to send to the tool which allows you to get around OS command-line length limits. This example adds the inputs and libraries to a response file, but passes the linker flags directly on the command line: tool("link") { command = "link -o {{output}} {{ldflags}} @{{output}}.rsp" rspfile = "{{output}}.rsp" rspfile_content = "{{inputs}} {{solibs}} {{libs}}" }Expansions for tool variables All paths are relative to the root build directory, which is the current directory for running all tools. These expansions are available to all tools: {{label}} The label of the current target. This is typically used in the "description" field for link tools. The toolchain will be omitted from the label for targets in the default toolchain, and will be included for targets in other toolchains. {{output}} The relative path and name of the output(s) of the current build step. If there is more than one output, this will expand to a list of all of them. Example: "out/base/my_file.o" {{target_gen_dir}} {{target_out_dir}} The directory of the generated file and output directories, respectively, for the current target. There is no trailing slash. Example: "out/base/test" {{target_output_name}} The short name of the current target with no path information, or the value of the "output_name" variable if one is specified in the target. This will include the "output_prefix" if any. Example: "libfoo" for the target named "foo" and an output prefix for the linker tool of "lib". Compiler tools have the notion of a single input and a single output, along with a set of compiler-specific flags. The following expansions are available: {{cflags}} {{cflags_c}} {{cflags_cc}} {{cflags_objc}} {{cflags_objcc}} {{defines}} {{include_dirs}} Strings correspond that to the processed flags/defines/include directories specified for the target. Example: "--enable-foo --enable-bar" Defines will be prefixed by "-D" and include directories will be prefixed by "-I" (these work with Posix tools as well as Microsoft ones). {{source}} The relative path and name of the current input file. Example: "../../base/my_file.cc" {{source_file_part}} The file part of the source including the extension (with no directory information). Example: "foo.cc" {{source_name_part}} The filename part of the source file with no directory or extension. Example: "foo" {{source_gen_dir}} {{source_out_dir}} The directory in the generated file and output directories, respectively, for the current input file. If the source file is in the same directory as the target is declared in, they will will be the same as the "target" versions above. Example: "gen/base/test" Linker tools have multiple inputs and (potentially) multiple outputs The following expansions are available: {{inputs}} {{inputs_newline}} Expands to the inputs to the link step. This will be a list of object files and static libraries. Example: "obj/foo.o obj/bar.o obj/somelibrary.a" The "_newline" version will separate the input files with newlines instead of spaces. This is useful in response files: some linkers can take a "-filelist" flag which expects newline separated files, and some Microsoft tools have a fixed-sized buffer for parsing each line of a response file. {{ldflags}} Expands to the processed set of ldflags and library search paths specified for the target. Example: "-m64 -fPIC -pthread -L/usr/local/mylib" {{libs}} Expands to the list of system libraries to link to. Each will be prefixed by the "lib_prefix". As a special case to support Mac, libraries with names ending in ".framework" will be added to the {{libs}} with "-framework" preceeding it, and the lib prefix will be ignored. Example: "-lfoo -lbar" {{output_extension}} The value of the "output_extension" variable in the target, or the value of the "default_output_extension" value in the tool if the target does not specify an output extension. Example: ".so" {{solibs}} Extra libraries from shared library dependencide not specified in the {{inputs}}. This is the list of link_output files from shared libraries (if the solink tool specifies a "link_output" variable separate from the "depend_output"). These should generally be treated the same as libs by your tool. Example: "libfoo.so libbar.so" The copy tool allows the common compiler/linker substitutions, plus {{source}} which is the source of the copy. The stamp tool allows only the common tool substitutions.Separate linking and dependencies for shared libraries Shared libraries are special in that not all changes to them require that dependent targets be re-linked. If the shared library is changed but no imports or exports are different, dependent code needn't be relinked, which can speed up the build. If your link step can output a list of exports from a shared library and writes the file only if the new one is different, the timestamp of this file can be used for triggering re-links, while the actual shared library would be used for linking. You will need to specify restat = true in the linker tool to make this work, so Ninja will detect if the timestamp of the dependency file has changed after linking (otherwise it will always assume that running a command updates the output): tool("solink") { command = "..." outputs = [ "{{root_out_dir}}/{{target_output_name}}{{output_extension}}", "{{root_out_dir}}/{{target_output_name}}{{output_extension}}.TOC", ] link_output = "{{root_out_dir}}/{{target_output_name}}{{output_extension}}" depend_output = "{{root_out_dir}}/{{target_output_name}}{{output_extension}}.TOC" restat = true }Example toolchain("my_toolchain") { # Put these at the top to apply to all tools below. lib_prefix = "-l" lib_dir_prefix = "-L" tool("cc") { command = "gcc {{source}} -o {{output}}" outputs = [ "{{source_out_dir}}/{{source_name_part}}.o" ] description = "GCC {{source}}" } tool("cxx") { command = "g++ {{source}} -o {{output}}" outputs = [ "{{source_out_dir}}/{{source_name_part}}.o" ] description = "G++ {{source}}" } }toolchain: Defines a toolchain. A toolchain is a set of commands and build flags used to compile the source code. You can have more than one toolchain in use at once in a build.Functions and variables tool() The tool() function call specifies the commands commands to run for a given step. See "gn help tool". toolchain_args() List of arguments to pass to the toolchain when invoking this toolchain. This applies only to non-default toolchains. See "gn help toolchain_args" for more. deps Dependencies of this toolchain. These dependencies will be resolved before any target in the toolchain is compiled. To avoid circular dependencies these must be targets defined in another toolchain. This is expressed as a list of targets, and generally these targets will always specify a toolchain: deps = [ "//foo/bar:baz(//build/toolchain:bootstrap)" ] This concept is somewhat inefficient to express in Ninja (it requires a lot of duplicate of rules) so should only be used when absolutely necessary. concurrent_links In integer expressing the number of links that Ninja will perform in parallel. GN will create a pool for shared library and executable link steps with this many processes. Since linking is memory- and I/O-intensive, projects with many large targets may want to limit the number of parallel steps to avoid overloading the computer. Since creating static libraries is generally not as intensive there is no limit to "alink" steps. Defaults to 0 which Ninja interprets as "no limit". The value used will be the one from the default toolchain of the current build.Invoking targets in toolchains: By default, when a target depends on another, there is an implicit toolchain label that is inherited, so the dependee has the same one as the dependent. You can override this and refer to any other toolchain by explicitly labeling the toolchain to use. For example: data_deps = [ "//plugins:mine(//toolchains:plugin_toolchain)" ] The string "//build/toolchains:plugin_toolchain" is a label that identifies the toolchain declaration for compiling the sources. To load a file in an alternate toolchain, GN does the following: 1. Loads the file with the toolchain definition in it (as determined by the toolchain label). 2. Re-runs the master build configuration file, applying the arguments specified by the toolchain_args section of the toolchain definition (see "gn help toolchain_args"). 3. Loads the destination build file in the context of the configuration file in the previous step.Example: toolchain("plugin_toolchain") { concurrent_links = 8 tool("cc") { command = "gcc {{source}}" ... } toolchain_args() { is_plugin = true is_32bit = true is_64bit = false } }toolchain_args: Set build arguments for toolchain build setup. Used inside a toolchain definition to pass arguments to an alternate toolchain's invocation of the build. When you specify a target using an alternate toolchain, the master build configuration file is re-interpreted in the context of that toolchain (see "gn help toolchain"). The toolchain_args function allows you to control the arguments passed into this alternate invocation of the build. Any default system arguments or arguments passed in on the command- line will also be passed to the alternate invocation unless explicitly overridden by toolchain_args. The toolchain_args will be ignored when the toolchain being defined is the default. In this case, it's expected you want the default argument values. See also "gn help buildargs" for an overview of these arguments.Example: toolchain("my_weird_toolchain") { ... toolchain_args() { # Override the system values for a generic Posix system. is_win = false is_posix = true # Pass this new value for specific setup for my toolchain. is_my_weird_system = true } }write_file: Write a file to disk. write_file(filename, data) If data is a list, the list will be written one-item-per-line with no quoting or brackets. If the file exists and the contents are identical to that being written, the file will not be updated. This will prevent unnecessary rebuilds of targets that depend on this file. TODO(brettw) we probably need an optional third argument to control list formatting.Arguments: filename Filename to write. This must be within the output directory. data: The list or string to write.current_cpu: The processor architecture of the current toolchain. The build configuration usually sets this value based on the value of "host_cpu" (see "gn help host_cpu") and then threads this through the toolchain definitions to ensure that it always reflects the appropriate value. This value is not used internally by GN for any purpose. It is set it to the empty string ("") by default but is declared so that it can be overridden on the command line if so desired. See "gn help target_cpu" for a list of common values returned.current_os: The operating system of the current toolchain. The build configuration usually sets this value based on the value of "target_os" (see "gn help target_os"), and then threads this through the toolchain definitions to ensure that it always reflects the appropriate value. This value is not used internally by GN for any purpose. It is set it to the empty string ("") by default but is declared so that it can be overridden on the command line if so desired. See "gn help target_os" for a list of common values returned.current_toolchain: Label of the current toolchain. A fully-qualified label representing the current toolchain. You can use this to make toolchain-related decisions in the build. See also "default_toolchain".Example: if (current_toolchain == "//build:64_bit_toolchain") { executable("output_thats_64_bit_only") { ...default_toolchain: [string] Label of the default toolchain. A fully-qualified label representing the default toolchain, which may not necessarily be the current one (see "current_toolchain").host_cpu: The processor architecture that GN is running on. This is value is exposed so that cross-compile toolchains can access the host architecture when needed. The value should generally be considered read-only, but it can be overriden in order to handle unusual cases where there might be multiple plausible values for the host architecture (e.g., if you can do either 32-bit or 64-bit builds). The value is not used internally by GN for any purpose.Some possible values: - "x64" - "x86"host_os: [string] The operating system that GN is running on. This value is exposed so that cross-compiles can access the host build system's settings. This value should generally be treated as read-only. It, however, is not used internally by GN for any purpose.Some possible values: - "linux" - "mac" - "win"python_path: Absolute path of Python. Normally used in toolchain definitions if running some command requires Python. You will normally not need this when invoking scripts since GN automatically finds it for you.root_build_dir: [string] Directory where build commands are run. This is the root build output directory which will be the current directory when executing all compilers and scripts. Most often this is used with rebase_path (see "gn help rebase_path") to convert arguments to be relative to a script's current directory.root_gen_dir: Directory for the toolchain's generated files. Absolute path to the root of the generated output directory tree for the current toolchain. An example would be "//out/Debug/gen" for the default toolchain, or "//out/Debug/arm/gen" for the "arm" toolchain. This is primarily useful for setting up include paths for generated files. If you are passing this to a script, you will want to pass it through rebase_path() (see "gn help rebase_path") to convert it to be relative to the build directory. See also "target_gen_dir" which is usually a better location for generated files. It will be inside the root generated dir.root_out_dir: [string] Root directory for toolchain output files. Absolute path to the root of the output directory tree for the current toolchain. It will not have a trailing slash. For the default toolchain this will be the same as the root_build_dir. An example would be "//out/Debug" for the default toolchain, or "//out/Debug/arm" for the "arm" toolchain. This is primarily useful for setting up script calls. If you are passing this to a script, you will want to pass it through rebase_path() (see "gn help rebase_path") to convert it to be relative to the build directory. See also "target_out_dir" which is usually a better location for output files. It will be inside the root output dir.Example: action("myscript") { # Pass the output dir to the script. args = [ "-o", rebase_path(root_out_dir, root_build_dir) ] }target_cpu: The desired cpu architecture for the build. This value should be used to indicate the desired architecture for the primary objects of the build. It will match the cpu architecture of the default toolchain. In many cases, this is the same as "host_cpu", but in the case of cross-compiles, this can be set to something different. This value is different from "current_cpu" in that it can be referenced from inside any toolchain. This value can also be ignored if it is not needed or meaningful for a project. This value is not used internally by GN for any purpose, so it may be set to whatever value is needed for the build. GN defaults this value to the empty string ("") and the configuration files should set it to an appropriate value (e.g., setting it to the value of "host_cpu") if it is not overridden on the command line or in the args.gn file. Where practical, use one of the following list of common values:Possible values: - "x86" - "x64" - "arm" - "arm64" - "mipsel"target_gen_dir: Directory for a target's generated files. Absolute path to the target's generated file directory. This will be the "root_gen_dir" followed by the relative path to the current build file. If your file is in "//tools/doom_melon" then target_gen_dir would be "//out/Debug/gen/tools/doom_melon". It will not have a trailing slash. This is primarily useful for setting up include paths for generated files. If you are passing this to a script, you will want to pass it through rebase_path() (see "gn help rebase_path") to convert it to be relative to the build directory. See also "gn help root_gen_dir".Example: action("myscript") { # Pass the generated output dir to the script. args = [ "-o", rebase_path(target_gen_dir, root_build_dir) ] }target_os: The desired operating system for the build. This value should be used to indicate the desired operating system for the primary object(s) of the build. It will match the OS of the default toolchain. In many cases, this is the same as "host_os", but in the case of cross-compiles, it may be different. This variable differs from "current_os" in that it can be referenced from inside any toolchain and will always return the initial value. This should be set to the most specific value possible. So, "android" or "chromeos" should be used instead of "linux" where applicable, even though Android and ChromeOS are both Linux variants. This can mean that one needs to write if (target_os == "android" || target_os == "linux") { # ... } and so forth. This value is not used internally by GN for any purpose, so it may be set to whatever value is needed for the build. GN defaults this value to the empty string ("") and the configuration files should set it to an appropriate value (e.g., setting it to the value of "host_os") if it is not set via the command line or in the args.gn file. Where practical, use one of the following list of common values:Possible values: - "android" - "chromeos" - "ios" - "linux" - "nacl" - "mac" - "win"target_out_dir: [string] Directory for target output files. Absolute path to the target's generated file directory. If your current target is in "//tools/doom_melon" then this value might be "//out/Debug/obj/tools/doom_melon". It will not have a trailing slash. This is primarily useful for setting up arguments for calling scripts. If you are passing this to a script, you will want to pass it through rebase_path() (see "gn help rebase_path") to convert it to be relative to the build directory. See also "gn help root_out_dir".Example: action("myscript") { # Pass the output dir to the script. args = [ "-o", rebase_path(target_out_dir, root_build_dir) ] }all_dependent_configs: Configs to be forced on dependents. A list of config labels. All targets depending on this one, and recursively, all targets depending on those, will have the configs listed in this variable added to them. These configs will also apply to the current target. This addition happens in a second phase once a target and all of its dependencies have been resolved. Therefore, a target will not see these force-added configs in their "configs" variable while the script is running, and then can not be removed. As a result, this capability should generally only be used to add defines and include directories necessary to compile a target's headers. See also "public_configs".Ordering of flags and values: 1. Those set on the current target (not in a config). 2. Those set on the "configs" on the target in order that the configs appear in the list. 3. Those set on the "all_dependent_configs" on the target in order that the configs appear in the list. 4. Those set on the "public_configs" on the target in order that those configs appear in the list. 5. all_dependent_configs pulled from dependencies, in the order of the "deps" list. This is done recursively. If a config appears more than once, only the first occurance will be used. 6. public_configs pulled from dependencies, in the order of the "deps" list. If a dependency is public, they will be applied recursively.allow_circular_includes_from: Permit includes from deps. A list of target labels. Must be a subset of the target's "deps". These targets will be permitted to include headers from the current target despite the dependency going in the opposite direction.Tedious exposition Normally, for a file in target A to include a file from target B, A must list B as a dependency. This invariant is enforced by the "gn check" command (and the --check flag to "gn gen"). Sometimes, two targets might be the same unit for linking purposes (two source sets or static libraries that would always be linked together in a final executable or shared library). In this case, you want A to be able to include B's headers, and B to include A's headers. This list, if specified, lists which of the dependencies of the current target can include header files from the current target. That is, if A depends on B, B can only include headers from A if it is in A's allow_circular_includes_from list.Example source_set("a") { deps = [ ":b", ":c" ] allow_circular_includes_from = [ ":b" ] ... }args: Arguments passed to an action. For action and action_foreach targets, args is the list of arguments to pass to the script. Typically you would use source expansion (see "gn help source_expansion") to insert the source file names. See also "gn help action" and "gn help action_foreach".cflags*: Flags passed to the C compiler. A list of strings. "cflags" are passed to all invocations of the C, C++, Objective C, and Objective C++ compilers. To target one of these variants individually, use "cflags_c", "cflags_cc", "cflags_objc", and "cflags_objcc", respectively. These variant-specific versions will be appended to the "cflags".Ordering of flags and values: 1. Those set on the current target (not in a config). 2. Those set on the "configs" on the target in order that the configs appear in the list. 3. Those set on the "all_dependent_configs" on the target in order that the configs appear in the list. 4. Those set on the "public_configs" on the target in order that those configs appear in the list. 5. all_dependent_configs pulled from dependencies, in the order of the "deps" list. This is done recursively. If a config appears more than once, only the first occurance will be used. 6. public_configs pulled from dependencies, in the order of the "deps" list. If a dependency is public, they will be applied recursively.cflags*: Flags passed to the C compiler. A list of strings. "cflags" are passed to all invocations of the C, C++, Objective C, and Objective C++ compilers. To target one of these variants individually, use "cflags_c", "cflags_cc", "cflags_objc", and "cflags_objcc", respectively. These variant-specific versions will be appended to the "cflags".Ordering of flags and values: 1. Those set on the current target (not in a config). 2. Those set on the "configs" on the target in order that the configs appear in the list. 3. Those set on the "all_dependent_configs" on the target in order that the configs appear in the list. 4. Those set on the "public_configs" on the target in order that those configs appear in the list. 5. all_dependent_configs pulled from dependencies, in the order of the "deps" list. This is done recursively. If a config appears more than once, only the first occurance will be used. 6. public_configs pulled from dependencies, in the order of the "deps" list. If a dependency is public, they will be applied recursively.cflags*: Flags passed to the C compiler. A list of strings. "cflags" are passed to all invocations of the C, C++, Objective C, and Objective C++ compilers. To target one of these variants individually, use "cflags_c", "cflags_cc", "cflags_objc", and "cflags_objcc", respectively. These variant-specific versions will be appended to the "cflags".Ordering of flags and values: 1. Those set on the current target (not in a config). 2. Those set on the "configs" on the target in order that the configs appear in the list. 3. Those set on the "all_dependent_configs" on the target in order that the configs appear in the list. 4. Those set on the "public_configs" on the target in order that those configs appear in the list. 5. all_dependent_configs pulled from dependencies, in the order of the "deps" list. This is done recursively. If a config appears more than once, only the first occurance will be used. 6. public_configs pulled from dependencies, in the order of the "deps" list. If a dependency is public, they will be applied recursively.cflags*: Flags passed to the C compiler. A list of strings. "cflags" are passed to all invocations of the C, C++, Objective C, and Objective C++ compilers. To target one of these variants individually, use "cflags_c", "cflags_cc", "cflags_objc", and "cflags_objcc", respectively. These variant-specific versions will be appended to the "cflags".Ordering of flags and values: 1. Those set on the current target (not in a config). 2. Those set on the "configs" on the target in order that the configs appear in the list. 3. Those set on the "all_dependent_configs" on the target in order that the configs appear in the list. 4. Those set on the "public_configs" on the target in order that those configs appear in the list. 5. all_dependent_configs pulled from dependencies, in the order of the "deps" list. This is done recursively. If a config appears more than once, only the first occurance will be used. 6. public_configs pulled from dependencies, in the order of the "deps" list. If a dependency is public, they will be applied recursively.cflags*: Flags passed to the C compiler. A list of strings. "cflags" are passed to all invocations of the C, C++, Objective C, and Objective C++ compilers. To target one of these variants individually, use "cflags_c", "cflags_cc", "cflags_objc", and "cflags_objcc", respectively. These variant-specific versions will be appended to the "cflags".Ordering of flags and values: 1. Those set on the current target (not in a config). 2. Those set on the "configs" on the target in order that the configs appear in the list. 3. Those set on the "all_dependent_configs" on the target in order that the configs appear in the list. 4. Those set on the "public_configs" on the target in order that those configs appear in the list. 5. all_dependent_configs pulled from dependencies, in the order of the "deps" list. This is done recursively. If a config appears more than once, only the first occurance will be used. 6. public_configs pulled from dependencies, in the order of the "deps" list. If a dependency is public, they will be applied recursively.check_includes: [boolean] Controls whether a target's files are checked. When true (the default), the "gn check" command (as well as "gn gen" with the --check flag) will check this target's sources and headers for proper dependencies. When false, the files in this target will be skipped by default. This does not affect other targets that depend on the current target, it just skips checking the includes of the current target's files.Controlling includes individually If only certain includes are problematic, you can annotate them individually rather than disabling header checking on an entire target. Add the string "nogncheck" to the include line: #include "foo/something_weird.h" // nogncheck (bug 12345) It is good form to include a reference to a bug (if the include is improper, or some other comment expressing why the header checker doesn't work for this particular case. The most common reason to need "nogncheck" is conditional includes. The header checker does not understand the preprocessor, so may flag some includes as improper even if the dependencies and #defines are always matched correctly: #if defined(ENABLE_DOOM_MELON) #include "doom_melon/beam_controller.h" // nogncheck #endifExample source_set("busted_includes") { # This target's includes are messed up, exclude it from checking. check_includes = false ... }complete_static_lib: [boolean] Links all deps into a static library. A static library normally doesn't include code from dependencies, but instead forwards the static libraries and source sets in its deps up the dependency chain until a linkable target (an executable or shared library) is reached. The final linkable target only links each static library once, even if it appears more than once in its dependency graph. In some cases the static library might be the final desired output. For example, you may be producing a static library for distribution to third parties. In this case, the static library should include code for all dependencies in one complete package. Since GN does not unpack static libraries to forward their contents up the dependency chain, it is an error for complete static libraries to depend on other static libraries.Example static_library("foo") { complete_static_lib = true deps = [ "bar" ] }configs: Configs applying to this target. A list of config labels. The include_dirs, defines, etc. in each config are appended in the order they appear to the compile command for each file in the target. They will appear after the include_dirs, defines, etc. that the target sets directly. The build configuration script will generally set up the default configs applying to a given target type (see "set_defaults"). When a target is being defined, it can add to or remove from this list.Ordering of flags and values: 1. Those set on the current target (not in a config). 2. Those set on the "configs" on the target in order that the configs appear in the list. 3. Those set on the "all_dependent_configs" on the target in order that the configs appear in the list. 4. Those set on the "public_configs" on the target in order that those configs appear in the list. 5. all_dependent_configs pulled from dependencies, in the order of the "deps" list. This is done recursively. If a config appears more than once, only the first occurance will be used. 6. public_configs pulled from dependencies, in the order of the "deps" list. If a dependency is public, they will be applied recursively.Example: static_library("foo") { configs -= "//build:no_rtti" # Don't use the default RTTI config. configs += ":mysettings" # Add some of our own settings. }data: Runtime data file dependencies. Lists files or directories required to run the given target. These are typically data files or directories of data files. The paths are interpreted as being relative to the current build file. Since these are runtime dependencies, they do not affect which targets are built or when. To declare input files to a script, use "inputs". Appearing in the "data" section does not imply any special handling such as copying them to the output directory. This is just used for declaring runtime dependencies. Runtime dependencies can be queried using the "runtime_deps" category of "gn desc" or written during build generation via "--runtime-deps-list-file". GN doesn't require data files to exist at build-time. So actions that produce files that are in turn runtime dependencies can list those generated files both in the "outputs" list as well as the "data" list. By convention, directories are be listed with a trailing slash: data = [ "test/data/" ] However, no verification is done on these so GN doesn't enforce this. The paths are just rebased and passed along when requested. See "gn help runtime_deps" for how these are used.data_deps: Non-linked dependencies. A list of target labels. Specifies dependencies of a target that are not actually linked into the current target. Such dependencies will built and will be available at runtime. This is normally used for things like plugins or helper programs that a target needs at runtime. See also "gn help deps" and "gn help data".Example: executable("foo") { deps = [ "//base" ] data_deps = [ "//plugins:my_runtime_plugin" ] }defines: C preprocessor defines. A list of strings These strings will be passed to the C/C++ compiler as #defines. The strings may or may not include an "=" to assign a value.Ordering of flags and values: 1. Those set on the current target (not in a config). 2. Those set on the "configs" on the target in order that the configs appear in the list. 3. Those set on the "all_dependent_configs" on the target in order that the configs appear in the list. 4. Those set on the "public_configs" on the target in order that those configs appear in the list. 5. all_dependent_configs pulled from dependencies, in the order of the "deps" list. This is done recursively. If a config appears more than once, only the first occurance will be used. 6. public_configs pulled from dependencies, in the order of the "deps" list. If a dependency is public, they will be applied recursively.Example: defines = [ "AWESOME_FEATURE", "LOG_LEVEL=3" ]depfile: [string] File name for input dependencies for actions. If nonempty, this string specifies that the current action or action_foreach target will generate the given ".d" file containing the dependencies of the input. Empty or unset means that the script doesn't generate the files. The .d file should go in the target output directory. If you have more than one source file that the script is being run over, you can use the output file expansions described in "gn help action_foreach" to name the .d file according to the input. The format is that of a Makefile, and all of the paths should be relative to the root build directory.Example: action_foreach("myscript_target") { script = "myscript.py" sources = [ ... ] # Locate the depfile in the output directory named like the # inputs but with a ".d" appended. depfile = "$relative_target_output_dir/{{source_name}}.d" # Say our script uses "-o <d file>" to indicate the depfile. args = [ "{{source}}", "-o", depfile ] }deps: Private linked dependencies. A list of target labels. Specifies private dependencies of a target. Shared and dynamic libraries will be linked into the current target. Other target types that can't be linked (like actions and groups) listed in "deps" will be treated as "data_deps". Likewise, if the current target isn't linkable, then all deps will be treated as "data_deps". These dependencies are private in that it does not grant dependent targets the ability to include headers from the dependency, and direct dependent configs are not forwarded. See also "public_deps" and "data_deps".forward_dependent_configs_from A list of target labels. DEPRECATED. Use public_deps instead which will have the same effect. Exposes the public_configs from a private dependent target as public_configs of the current one. Each label in this list must also be in the deps. Generally you should use public_deps instead of this variable to express the concept of exposing a dependency as part of a target's public API. We're considering removing this variable.Discussion Sometimes you depend on a child library that exports some necessary configuration via public_configs. If your target in turn exposes the child library's headers in its public headers, it might mean that targets that depend on you won't work: they'll be seeing the child library's code but not the necessary configuration. This list specifies which of your deps' direct dependent configs to expose as your own.Examples If we use a given library "a" from our public headers: deps = [ ":a", ":b", ... ] forward_dependent_configs_from = [ ":a" ] This example makes a "transparent" target that forwards a dependency to another: group("frob") { if (use_system_frob) { deps = ":system_frob" } else { deps = "//third_party/fallback_frob" } forward_dependent_configs_from = deps }include_dirs: Additional include directories. A list of source directories. The directories in this list will be added to the include path for the files in the affected target.Ordering of flags and values: 1. Those set on the current target (not in a config). 2. Those set on the "configs" on the target in order that the configs appear in the list. 3. Those set on the "all_dependent_configs" on the target in order that the configs appear in the list. 4. Those set on the "public_configs" on the target in order that those configs appear in the list. 5. all_dependent_configs pulled from dependencies, in the order of the "deps" list. This is done recursively. If a config appears more than once, only the first occurance will be used. 6. public_configs pulled from dependencies, in the order of the "deps" list. If a dependency is public, they will be applied recursively.Example: include_dirs = [ "src/include", "//third_party/foo" ]inputs: Additional compile-time dependencies. Inputs are compile-time dependencies of the current target. This means that all inputs must be available before compiling any of the sources or executing any actions. Inputs are typically only used for action and action_foreach targets.Inputs for actions For action and action_foreach targets, inputs should be the inputs to script that don't vary. These should be all .py files that the script uses via imports (the main script itself will be an implcit dependency of the action so need not be listed). For action targets, inputs should be the entire set of inputs the script needs. For action_foreach targets, inputs should be the set of dependencies that don't change. These will be applied to each script invocation over the sources. Note that another way to declare input dependencies from an action is to have the action write a depfile (see "gn help depfile"). This allows the script to dynamically write input dependencies, that might not be known until actually executing the script. This is more efficient than doing processing while running GN to determine the inputs, and is easier to keep in-sync than hardcoding the list.Inputs for binary targets Any input dependencies will be resolved before compiling any sources. Normally, all actions that a target depends on will be run before any files in a target are compiled. So if you depend on generated headers, you do not typically need to list them in the inputs section.Example action("myscript") { script = "domything.py" inputs = [ "input.data" ] }ldflags: Flags passed to the linker. A list of strings. These flags are passed on the command-line to the linker and generally specify various linking options. Most targets will not need these and will use "libs" and "lib_dirs" instead. ldflags are NOT pushed to dependents, so applying ldflags to source sets or static libraries will be a no-op. If you want to apply ldflags to dependent targets, put them in a config and set it in the all_dependent_configs or public_configs.lib_dirs: Additional library directories. A list of directories. Specifies additional directories passed to the linker for searching for the required libraries. If an item is not an absolute path, it will be treated as being relative to the current build file. libs and lib_dirs work differently than other flags in two respects. First, then are inherited across static library boundaries until a shared library or executable target is reached. Second, they are uniquified so each one is only passed once (the first instance of it will be the one used).Ordering of flags and values: 1. Those set on the current target (not in a config). 2. Those set on the "configs" on the target in order that the configs appear in the list. 3. Those set on the "all_dependent_configs" on the target in order that the configs appear in the list. 4. Those set on the "public_configs" on the target in order that those configs appear in the list. 5. all_dependent_configs pulled from dependencies, in the order of the "deps" list. This is done recursively. If a config appears more than once, only the first occurance will be used. 6. public_configs pulled from dependencies, in the order of the "deps" list. If a dependency is public, they will be applied recursively.Example: lib_dirs = [ "/usr/lib/foo", "lib/doom_melon" ]libs: Additional libraries to link. A list of strings. These files will be passed to the linker, which will generally search the library include path. Unlike a normal list of files, they will be passed to the linker unmodified rather than being treated as file names relative to the current build file. Generally you would set the "lib_dirs" so your library is found. If you need to specify a path, you can use "rebase_path" to convert a path to be relative to the build directory. When constructing the linker command, the "lib_prefix" attribute of the linker tool in the current toolchain will be prepended to each library. So your BUILD file should not specify the switch prefix (like "-l"). On Mac, libraries ending in ".framework" will be special-cased: the switch "-framework" will be prepended instead of the lib_prefix, and the ".framework" suffix will be trimmed. libs and lib_dirs work differently than other flags in two respects. First, then are inherited across static library boundaries until a shared library or executable target is reached. Second, they are uniquified so each one is only passed once (the first instance of it will be the one used).Ordering of flags and values: 1. Those set on the current target (not in a config). 2. Those set on the "configs" on the target in order that the configs appear in the list. 3. Those set on the "all_dependent_configs" on the target in order that the configs appear in the list. 4. Those set on the "public_configs" on the target in order that those configs appear in the list. 5. all_dependent_configs pulled from dependencies, in the order of the "deps" list. This is done recursively. If a config appears more than once, only the first occurance will be used. 6. public_configs pulled from dependencies, in the order of the "deps" list. If a dependency is public, they will be applied recursively.Examples: On Windows: libs = [ "ctl3d.lib" ] On Linux: libs = [ "ld" ]output_extension: Value to use for the output's file extension. Normally the file extension for a target is based on the target type and the operating system, but in rare cases you will need to override the name (for example to use "libfreetype.so.6" instead of libfreetype.so on Linux).output_name: Define a name for the output file other than the default. Normally the output name of a target will be based on the target name, so the target "//foo/bar:bar_unittests" will generate an output file such as "bar_unittests.exe" (using Windows as an example). Sometimes you will want an alternate name to avoid collisions or if the internal name isn't appropriate for public distribution. The output name should have no extension or prefixes, these will be added using the default system rules. For example, on Linux an output name of "foo" will produce a shared library "libfoo.so". This variable is valid for all binary output target types.Example: static_library("doom_melon") { output_name = "fluffy_bunny" }outputs: Output files for actions and copy targets. Outputs is valid for "copy", "action", and "action_foreach" target types and indicates the resulting files. The values may contain source expansions to generate the output names from the sources (see "gn help source_expansion"). For copy targets, the outputs is the destination for the copied file(s). For actions, the outputs should be the list of files generated by the script.precompiled_header: [string] Header file to precompile. Precompiled headers will be used when a target specifies this value, or a config applying to this target specifies this value. In addition, the tool corresponding to the source files must also specify precompiled headers (see "gn help tool"). The tool will also specify what type of precompiled headers to use. The precompiled header/source variables can be specified on a target or a config, but must be the same for all configs applying to a given target since a target can only have one precompiled header.MSVC precompiled headers When using MSVC-style precompiled headers, the "precompiled_header" value is a string corresponding to the header. This is NOT a path to a file that GN recognises, but rather the exact string that appears in quotes after an #include line in source code. The compiler will match this string against includes or forced includes (/FI). MSVC also requires a source file to compile the header with. This must be specified by the "precompiled_source" value. In contrast to the header value, this IS a GN-style file name, and tells GN which source file to compile to make the .pch file used for subsequent compiles. If you use both C and C++ sources, the precompiled header and source file will be compiled using both tools. You will want to make sure to wrap C++ includes in __cplusplus #ifdefs so the file will compile in C mode. For example, if the toolchain specifies MSVC headers: toolchain("vc_x64") { ... tool("cxx") { precompiled_header_type = "msvc" ... You might make a config like this: config("use_precompiled_headers") { precompiled_header = "build/precompile.h" precompiled_source = "//build/precompile.cc" # Either your source files should #include "build/precompile.h" # first, or you can do this to force-include the header. cflags = [ "/FI$precompiled_header" ] } And then define a target that uses the config: executable("doom_melon") { configs += [ ":use_precompiled_headers" ] ...precompiled_source: [file name] Source file to precompile. The source file that goes along with the precompiled_header when using "msvc"-style precompiled headers. It will be implicitly added to the sources of the target. See "gn help precompiled_header".public: Declare public header files for a target. A list of files that other targets can include. These permissions are checked via the "check" command (see "gn help check"). If no public files are declared, other targets (assuming they have visibility to depend on this target can include any file in the sources list. If this variable is defined on a target, dependent targets may only include files on this whitelist. Header file permissions are also subject to visibility. A target must be visible to another target to include any files from it at all and the public headers indicate which subset of those files are permitted. See "gn help visibility" for more. Public files are inherited through the dependency tree. So if there is a dependency A -> B -> C, then A can include C's public headers. However, the same is NOT true of visibility, so unless A is in C's visibility list, the include will be rejected. GN only knows about files declared in the "sources" and "public" sections of targets. If a file is included that is not known to the build, it will be allowed.Examples: These exact files are public: public = [ "foo.h", "bar.h" ] No files are public (no targets may include headers from this one): public = []public_configs: Configs to be applied on dependents. A list of config labels. Targets directly depending on this one will have the configs listed in this variable added to them. These configs will also apply to the current target. This addition happens in a second phase once a target and all of its dependencies have been resolved. Therefore, a target will not see these force-added configs in their "configs" variable while the script is running, and then can not be removed. As a result, this capability should generally only be used to add defines and include directories necessary to compile a target's headers. See also "all_dependent_configs".Ordering of flags and values: 1. Those set on the current target (not in a config). 2. Those set on the "configs" on the target in order that the configs appear in the list. 3. Those set on the "all_dependent_configs" on the target in order that the configs appear in the list. 4. Those set on the "public_configs" on the target in order that those configs appear in the list. 5. all_dependent_configs pulled from dependencies, in the order of the "deps" list. This is done recursively. If a config appears more than once, only the first occurance will be used. 6. public_configs pulled from dependencies, in the order of the "deps" list. If a dependency is public, they will be applied recursively.public_deps: Declare public dependencies. Public dependencies are like private dependencies ("deps") but additionally express that the current target exposes the listed deps as part of its public API. This has several ramifications: - public_configs that are part of the dependency are forwarded to direct dependents. - Public headers in the dependency are usable by dependents (includes do not require a direct dependency or visibility). - If the current target is a shared library, other shared libraries that it publicly depends on (directly or indirectly) are propagated up the dependency tree to dependents for linking.Discussion Say you have three targets: A -> B -> C. C's visibility may allow B to depend on it but not A. Normally, this would prevent A from including any headers from C, and C's public_configs would apply only to B. If B lists C in its public_deps instead of regular deps, A will now inherit C's public_configs and the ability to include C's public headers. Generally if you are writing a target B and you include C's headers as part of B's public headers, or targets depending on B should consider B and C to be part of a unit, you should use public_deps instead of deps.Example # This target can include files from "c" but not from # "super_secret_implementation_details". executable("a") { deps = [ ":b" ] } shared_library("b") { deps = [ ":super_secret_implementation_details" ] public_deps = [ ":c" ] }script: Script file for actions. An absolute or buildfile-relative file name of a Python script to run for a action and action_foreach targets (see "gn help action" and "gn help action_foreach").sources: Source files for a target A list of files relative to the current buildfile.testonly: Declares a target must only be used for testing. Boolean. Defaults to false. When a target is marked "testonly = true", it must only be depended on by other test-only targets. Otherwise, GN will issue an error that the depenedency is not allowed. This feature is intended to prevent accidentally shipping test code in a final product.Example source_set("test_support") { testonly = true ... }visibility: A list of labels that can depend on a target. A list of labels and label patterns that define which targets can depend on the current one. These permissions are checked via the "check" command (see "gn help check"). If visibility is not defined, it defaults to public ("*"). If visibility is defined, only the targets with labels that match it can depend on the current target. The empty list means no targets can depend on the current target. Tip: Often you will want the same visibility for all targets in a BUILD file. In this case you can just put the definition at the top, outside of any target, and the targets will inherit that scope and see the definition.Patterns See "gn help label_pattern" for more details on what types of patterns are supported. If a toolchain is specified, only targets in that toolchain will be matched. If a toolchain is not specified on a pattern, targets in all toolchains will be matched.Examples Only targets in the current buildfile ("private"): visibility = [ ":*" ] No targets (used for targets that should be leaf nodes): visibility = [] Any target ("public", the default): visibility = [ "*" ] All targets in the current directory and any subdirectory: visibility = [ "./*" ] Any target in "//bar/BUILD.gn": visibility = [ "//bar:*" ] Any target in "//bar/" or any subdirectory thereof: visibility = [ "//bar/*" ] Just these specific targets: visibility = [ ":mything", "//foo:something_else" ] Any target in the current directory and any subdirectory thereof, plus any targets in "//bar/" and any subdirectory thereof. visibility = [ "./*", "//bar/*" ]Build Arguments Overview Build arguments are variables passed in from outside of the build that build files can query to determine how the build works.How build arguments are set First, system default arguments are set based on the current system. The built-in arguments are: - host_cpu - host_os - current_cpu - current_os - target_cpu - target_os If specified, arguments from the --args command line flag are used. If that flag is not specified, args from previous builds in the build directory will be used (this is in the file args.gn in the build directory). Last, for targets being compiled with a non-default toolchain, the toolchain overrides are applied. These are specified in the toolchain_args section of a toolchain definition. The use-case for this is that a toolchain may be building code for a different platform, and that it may want to always specify Posix, for example. See "gn help toolchain_args" for more. If you specify an override for a build argument that never appears in a "declare_args" call, a nonfatal error will be displayed.Examples gn args out/FooBar Create the directory out/FooBar and open an editor. You would type something like this into that file: enable_doom_melon=false os="android" gn gen out/FooBar --args="enable_doom_melon=true os=\"android\"" This will overwrite the build directory with the given arguments. (Note that the quotes inside the args command will usually need to be escaped for your shell to pass through strings values.)How build arguments are used If you want to use an argument, you use declare_args() and specify default values. These default values will apply if none of the steps listed in the "How build arguments are set" section above apply to the given argument, but the defaults will not override any of these. Often, the root build config file will declare global arguments that will be passed to all buildfiles. Individual build files can also specify arguments that apply only to those files. It is also useful to specify build args in an "import"-ed file if you want such arguments to apply to multiple buildfiles..gn file When gn starts, it will search the current directory and parent directories for a file called ".gn". This indicates the source root. You can override this detection by using the --root command-line argument The .gn file in the source root will be executed. The syntax is the same as a buildfile, but with very limited build setup-specific meaning. If you specify --root, by default GN will look for the file .gn in that directory. If you want to specify a different file, you can additionally pass --dotfile: gn gen out/Debug --root=/home/build --dotfile=/home/my_gn_file.gnVariables buildconfig [required] Label of the build config file. This file will be used to set up the build file execution environment for each toolchain. check_targets [optional] A list of labels and label patterns that should be checked when running "gn check" or "gn gen --check". If unspecified, all targets will be checked. If it is the empty list, no targets will be checked. The format of this list is identical to that of "visibility" so see "gn help visibility" for examples. exec_script_whitelist [optional] A list of .gn/.gni files (not labels) that have permission to call the exec_script function. If this list is defined, calls to exec_script will be checked against this list and GN will fail if the current file isn't in the list. This is to allow the use of exec_script to be restricted since is easy to use inappropriately. Wildcards are not supported. Files in the secondary_source tree (if defined) should be referenced by ignoring the secondary tree and naming them as if they are in the main tree. If unspecified, the ability to call exec_script is unrestricted. Example: exec_script_whitelist = [ "//base/BUILD.gn", "//build/my_config.gni", ] root [optional] Label of the root build target. The GN build will start by loading the build file containing this target name. This defaults to "//:" which will cause the file //BUILD.gn to be loaded. secondary_source [optional] Label of an alternate directory tree to find input files. When searching for a BUILD.gn file (or the build config file discussed above), the file will first be looked for in the source root. If it's not found, the secondary source root will be checked (which would contain a parallel directory hierarchy). This behavior is intended to be used when BUILD.gn files can't be checked in to certain source directories for whatever reason. The secondary source root must be inside the main source tree.Example .gn file contents buildconfig = "//build/config/BUILDCONFIG.gn" check_targets = [ "//doom_melon/*", # Check everything in this subtree. "//tools:mind_controlling_ant", # Check this specific target. ] root = "//:root" secondary_source = "//build/config/temporary_buildfiles/"GN build language grammarTokens GN build files are read as sequences of tokens. While splitting the file into tokens, the next token is the longest sequence of characters that form a valid token.White space and comments White space is comprised of spaces (U+0020), horizontal tabs (U+0009), carriage returns (U+000D), and newlines (U+000A). Comments start at the character "#" and stop at the next newline. White space and comments are ignored except that they may separate tokens that would otherwise combine into a single token.Identifiers Identifiers name variables and functions. identifier = letter { letter | digit } . letter = "A" ... "Z" | "a" ... "z" | "_" . digit = "0" ... "9" .Keywords The following keywords are reserved and may not be used as identifiers: else false if trueInteger literals An integer literal represents a decimal integer value. integer = [ "-" ] digit { digit } . Leading zeros and negative zero are disallowed.String literals A string literal represents a string value consisting of the quoted characters with possible escape sequences and variable expansions. string = `"` { char | escape | expansion } `"` . escape = `\` ( "$" | `"` | char ) . expansion = "$" ( identifier | "{" identifier "}" ) . char = /* any character except "$", `"`, or newline */ . After a backslash, certain sequences represent special characters: \" U+0022 quotation mark \$ U+0024 dollar sign \\ U+005C backslash All other backslashes represent themselves.Punctuation The following character sequences represent punctuation: + += == != ( ) - -= < <= [ ] ! = > >= { } && || . ,Grammar The input tokens form a syntax tree following a context-free grammar: File = StatementList . Statement = Assignment | Call | Condition . Assignment = identifier AssignOp Expr . Call = identifier "(" [ ExprList ] ")" [ Block ] . Condition = "if" "(" Expr ")" Block [ "else" ( Condition | Block ) ] . Block = "{" StatementList "}" . StatementList = { Statement } . Expr = UnaryExpr | Expr BinaryOp Expr . UnaryExpr = PrimaryExpr | UnaryOp UnaryExpr . PrimaryExpr = identifier | integer | string | Call | identifier "[" Expr "]" | identifier "." identifier | "(" Expr ")" | "[" [ ExprList [ "," ] ] "]" . ExprList = Expr { "," Expr } . AssignOp = "=" | "+=" | "-=" . UnaryOp = "!" . BinaryOp = "+" | "-" // highest priority | "<" | "<=" | ">" | ">=" | "==" | "!=" | "&&" | "||" . // lowest priority All binary operators are left-associative.input_conversion: Specifies how to transform input to a variable. input_conversion is an argument to read_file and exec_script that specifies how the result of the read operation should be converted into a variable. "" (the default) Discard the result and return None. "list lines" Return the file contents as a list, with a string for each line. The newlines will not be present in the result. The last line may or may not end in a newline. After splitting, each individual line will be trimmed of whitespace on both ends. "scope" Execute the block as GN code and return a scope with the resulting values in it. If the input was: a = [ "hello.cc", "world.cc" ] b = 26 and you read the result into a variable named "val", then you could access contents the "." operator on "val": sources = val.a some_count = val.b "string" Return the file contents into a single string. "value" Parse the input as if it was a literal rvalue in a buildfile. Examples of typical program output using this mode: [ "foo", "bar" ] (result will be a list) or "foo bar" (result will be a string) or 5 (result will be an integer) Note that if the input is empty, the result will be a null value which will produce an error if assigned to a variable. "trim ..." Prefixing any of the other transformations with the word "trim" will result in whitespace being trimmed from the beginning and end of the result before processing. Examples: "trim string" or "trim list lines" Note that "trim value" is useless because the value parser skips whitespace anyway.Label patterns A label pattern is a way of expressing one or more labels in a portion of the source tree. They are not general regular expressions. They can take the following forms only: - Explicit (no wildcard): "//foo/bar:baz" ":baz" - Wildcard target names: "//foo/bar:*" (all targets in the //foo/bar/BUILD.gn file) ":*" (all targets in the current build file) - Wildcard directory names ("*" is only supported at the end) "*" (all targets) "//foo/bar/*" (all targets in any subdir of //foo/bar) "./*" (all targets in the current build file or sub dirs) Any of the above forms can additionally take an explicit toolchain. In this case, the toolchain must be fully qualified (no wildcards are supported in the toolchain name). "//foo:bar(//build/toochain:mac)" An explicit target in an explicit toolchain. ":*(//build/toolchain/linux:32bit)" All targets in the current build file using the 32-bit Linux toolchain. "//foo/*(//build/toolchain:win)" All targets in //foo and any subdirectory using the Windows toolchain.Runtime dependencies Runtime dependencies of a target are exposed via the "runtime_deps" category of "gn desc" (see "gn help desc") or they can be written at build generation time via "--runtime-deps-list-file" (see "gn help --runtime-deps-list-file"). To a first approximation, the runtime dependencies of a target are the set of "data" files, data directories, and the shared libraries from all transitive dependencies. Executables and shared libraries are considered runtime dependencies of themselves.Details Executable targets and those executable targets' transitive dependencies are not considered unless that executable is listed in "data_deps". Otherwise, GN assumes that the executable (and everything it requires) is a build-time dependency only. Action and copy targets that are listed as "data_deps" will have all of their outputs and data files considered as runtime dependencies. Action and copy targets that are "deps" or "public_deps" will have only their data files considered as runtime dependencies. These targets can list an output file in both the "outputs" and "data" lists to force an output file as a runtime dependency in all cases. The results of static_library or source_set targets are not considered runtime dependencies since these are assumed to be intermediate targets only. If you need to list a static library as a runtime dependency, you can manually compute the .a/.lib file name for the current platform and list it in the "data" list of a target (possibly on the static library target itself). When a tool produces more than one output, only the first output is considered. For example, a shared library target may produce a .dll and a .lib file on Windows. Only the .dll file will be considered a runtime dependency.How Source Expansion Works Source expansion is used for the action_foreach and copy target types to map source file names to output file names or arguments. To perform source expansion in the outputs, GN maps every entry in the sources to every entry in the outputs list, producing the cross product of all combinations, expanding placeholders (see below). Source expansion in the args works similarly, but performing the placeholder substitution produces a different set of arguments for each invocation of the script. If no placeholders are found, the outputs or args list will be treated as a static list of literal file names that do not depend on the sources. See "gn help copy" and "gn help action_foreach" for more on how this is applied.Placeholders {{source}} The name of the source file including directory (*). This will generally be used for specifying inputs to a script in the "args" variable. "//foo/bar/baz.txt" => "../../foo/bar/baz.txt" {{source_file_part}} The file part of the source including the extension. "//foo/bar/baz.txt" => "baz.txt" {{source_name_part}} The filename part of the source file with no directory or extension. This will generally be used for specifying a transformation from a soruce file to a destination file with the same name but different extension. "//foo/bar/baz.txt" => "baz" {{source_dir}} The directory (*) containing the source file with no trailing slash. "//foo/bar/baz.txt" => "../../foo/bar" {{source_root_relative_dir}} The path to the source file's directory relative to the source root, with no leading "//" or trailing slashes. If the path is system-absolute, (beginning in a single slash) this will just return the path with no trailing slash. This value will always be the same, regardless of whether it appears in the "outputs" or "args" section. "//foo/bar/baz.txt" => "foo/bar" {{source_gen_dir}} The generated file directory (*) corresponding to the source file's path. This will be different than the target's generated file directory if the source file is in a different directory than the BUILD.gn file. "//foo/bar/baz.txt" => "gen/foo/bar" {{source_out_dir}} The object file directory (*) corresponding to the source file's path, relative to the build directory. this us be different than the target's out directory if the source file is in a different directory than the build.gn file. "//foo/bar/baz.txt" => "obj/foo/bar"(*) Note on directories Paths containing directories (except the source_root_relative_dir) will be different depending on what context the expansion is evaluated in. Generally it should "just work" but it means you can't concatenate strings containing these values with reasonable results. Details: source expansions can be used in the "outputs" variable, the "args" variable, and in calls to "process_file_template". The "args" are passed to a script which is run from the build directory, so these directories will relative to the build directory for the script to find. In the other cases, the directories will be source- absolute (begin with a "//") because the results of those expansions will be handled by GN internally.Examples Non-varying outputs: action("hardcoded_outputs") { sources = [ "input1.idl", "input2.idl" ] outputs = [ "$target_out_dir/output1.dat", "$target_out_dir/output2.dat" ] } The outputs in this case will be the two literal files given. Varying outputs: action_foreach("varying_outputs") { sources = [ "input1.idl", "input2.idl" ] outputs = [ "{{source_gen_dir}}/{{source_name_part}}.h", "{{source_gen_dir}}/{{source_name_part}}.cc" ] } Performing source expansion will result in the following output names: //out/Debug/obj/mydirectory/input1.h //out/Debug/obj/mydirectory/input1.cc //out/Debug/obj/mydirectory/input2.h //out/Debug/obj/mydirectory/input2.ccAvailable global switches Do “gn help --the_switch_you_want_help_on” for more. Individual commands may take command-specific switches not listed here. See the help on your specific command for more. ...

May 19, 2021 · 97 min · jiezi

关于chrome:Chrome浏览器上集成IE内核方案

Chrome浏览器上集成IE内核计划1. 架构图 双核性能的基本思路是,在chrome原有的render 治理的根底上,增加trident内核对象并在切换时将两个渲染的内核数据进行同步,进而将内核网络申请散发下来的数据,趋于统一,从而达到双核的无缝切换,内核数据同步次要包含cookie 数据同步和post 数据同步。 次要的流程包含: 窗口关联概要流程:由主窗口创立对应widget_host(即主窗口要bind的窗口)并与 trident 的容器窗口做bind(父子窗口关系设置) Cookie数据同步概要流程:V68代码chrome中的网络模型是在主过程管理网络过程和cookie,V87独立network网络模型,须要留神。须要将trident 内核网络数据的cookie的获取和存储均通过过程去治理。 Post,Refere等数据同步概要流程:渲染内核在开启新页面或者页面内刷新时会将一部分数据(次要包含post,refere等)放入到要导航的页面中,如果跳转的页面须要切换内核,那么须要这部分数据从内核中取出来,并将这些数据放入新的外围去导航。 2. chrome内核模型浏览器启动的时候会创立一个browser类, 启动流程期间会创立tab页面,而后渲染 StartupBrowserCreator::StartStartupBrowserCreator::LaunchBrowserStartupBrowserCreatorImpl::LaunchStartupBrowserCreatorImpl::DetermineURLsAndLaunchStartupBrowserCreatorImpl::RestoreOrCreateBrowserStartupBrowserCreatorImpl::OpenTabsInBrowservoid Navigate(NavigateParams* params)NavigatorImpl::NavigateToEntryNavigationRequest::BeginNavigation()NavigationHandleImpl::WillStartRequestNavigationURLLoader::Create3 IE内核接管RenderFrameHostImpl::NavigateTridentRenderFrameTrident::OnNavigateTridentView::NavigateTridentViewMessageHandlerImpl::OnNavigateTridentView::DoNavigateTridentControl::Navigate2CHtmlView::Navigate2 零碎函数

May 18, 2021 · 1 min · jiezi

关于chrome:玩转chrome常用启动命令

玩转chrome——罕用启动命令命令阐明--enable-logging启用日志--make-default-browser设默认--disable-http2禁用http2--user-agent="xxx"设置自定义代理--disable-gpu禁止gpu减速--no-sandbox --renderer-startup-dialog渲染器过程在启动时显示对话框--no-sandbox --gpu-startup-dialogGPU过程在启动时显示对话框-no-sandbox --plugin-startup-dialog插件过程启动时显示对话框--no-sandbox --ppapi-startup-dialogPPAPI子过程在启动时显示对话框

May 18, 2021 · 1 min · jiezi

关于chrome:谷歌开源项目命名规范

谷歌开源我的项目命名标准CEF和Chromium等

May 17, 2021 · 1 min · jiezi

关于chrome:浏览器内核分类

浏览器内核分类目前支流的浏览器内核次要为以下四种: Trident内核,代表产品Internet Explorer 微软IE Gecko内核,代表产品Mozilla Firefox火狐 Presto内核,代表产品Opera Blink内核,代表产品 Chrome,微软的Edge、360、QQ、2345 Webkite内核,代表产品,苹果的Safari 其中 Blink内核 已经基于 Webkite内核 演进而来

May 17, 2021 · 1 min · jiezi

关于chrome:Chromium和cef的区别

Chromium和cef的区别为何市场上的少数浏览器基于chromium开发而不是cef。 1 Chromium和cef的区别和分割chromium是谷歌主导的浏览器开源我的项目,基于chromium能够方便快捷定制一款浏览器,国内外少数浏览器也基于此开发。Cef是chromium我的项目的一个分支,抽离webkite和内核层,提供content层上的API接口,把简单的底层接口进行封装,更加敌对的给用户应用,少数用于客户端的开发,通过内置页面实现疾速开发客户端界面的成果。以后钉钉、企业微信、VSCode等少数客户端都应用此框架开发。他们都能够渲染网页,都是开源框架,chromium是浏览器的开源利用,针对浏览器的罕用性能做了大量工作,cef抽离渲染局部,利用在客户端的内嵌网页场景,阉割了局部性能,不便用户学习和应用。2 浏览器是否基于cef的开发2.1 如果能有哪些劣势,有哪些问题如果cef能满足日常的网页浏览,不便用户应用,基于此假如进行如下论证。 1、能够更加疾速的上手浏览器开发,起因:cef接口隔离比拟敌对,提供大量API即可实现满足渲染一个页面 2、疾速实现内核降级,起因:隔离比拟好,cef自身会把底层内核隔离进去一套接口,把下层利用给阉割掉。 3 问题难点如果要实现一个蕴含罕用性能的浏览器,须要先思考如何解决如下问题。 因为cef会阉割掉大多数应用层性能如:UI、Chrome、Content等,导致以后浏览器罕用性能在cef中须要本人实现。 3.1 如下技术点cef以后不反对,须要思考如何实现1、如何实现UI框架,反对各类UI展现、右键菜单、横幅、气泡,此UI框架波及最广,而且要求比拟对性能和扩展性、开发敌对等都有较高要求。 2、如何反对地址栏,实现地址栏各个性能,如联想提醒、历史记录联想、搜寻文字联想、珍藏联想、地址栏平安标识等等 3、如何反对珍藏,珍藏历史、珍藏搜寻、珍藏同步、珍藏本地保留和珍藏界面展现 4、如何反对开发这模式,比方:F12等各类HTML5的调试,此性能在cef能够通过开接口实现F12,cef自身反对一部分开发这模式,默认禁掉,须要从新捕捉音讯 5、如何反对各类内置页,页面的JS扩大接口、主页设置、各类选项设置页面,这个页面比拟多几十个,是chrome浏览器性能入口 6、如何反对插件性能,插件拖进、卸载和运行等 7、如何标签的治理,标签拖拽如:标签拖出新开一个浏览器,拖进能够合并2个浏览器窗口等 8、如何实现浏览器的同步机制 9、如何实现浏览器翻译性能 10、如何实现下载模块、多窗口模块、复原列表 11、如何实现鼠标手势、Favicon模块 12、UA性能、新标签页

May 17, 2021 · 1 min · jiezi

关于chrome:字符串编码转换

字符串编码转换字符串编码转换波及宽字节表示法与UTF-8表示法之间的转换、宽字节表示法与UTF-16表示法之间的转换、UTF-8表示法与UTF-16表示法之间的转换、UTF-16表示法于ASCII表示法之间的转换、ASCII表示法宽字节表示法之间的转换。 相干文件base/strings/utf\_string\_conversions.h // 字符串编码转换定义base/strings/utf\_string\_conversions.cc // 字符串编码转换实现base/strings/utf\_string\_conversions\_fuzzer.cc // 字符串编码转换实现办法定义// base/strings/utf_string_conversions.h namespace base {// These convert between UTF-8, -16, and -32 strings. They are potentially slow,// so avoid unnecessary conversions. The low-level versions return a boolean// indicating whether the conversion was 100% valid. In this case, it will still// do the best it can and put the result in the output buffer. The versions that// return strings ignore this error and just return the best conversion// possible.BASE_EXPORT bool WideToUTF8(const wchar_t* src, size_t src_len, std::string* output);BASE_EXPORT std::string WideToUTF8(WStringPiece wide) WARN_UNUSED_RESULT;BASE_EXPORT bool UTF8ToWide(const char* src, size_t src_len, std::wstring* output);BASE_EXPORT std::wstring UTF8ToWide(StringPiece utf8) WARN_UNUSED_RESULT;BASE_EXPORT bool WideToUTF16(const wchar_t* src, size_t src_len, std::u16string* output);BASE_EXPORT std::u16string WideToUTF16(WStringPiece wide) WARN_UNUSED_RESULT;BASE_EXPORT bool UTF16ToWide(const char16_t* src, size_t src_len, std::wstring* output);BASE_EXPORT std::wstring UTF16ToWide(StringPiece16 utf16) WARN_UNUSED_RESULT;BASE_EXPORT bool UTF8ToUTF16(const char* src, size_t src_len, std::u16string* output);BASE_EXPORT std::u16string UTF8ToUTF16(StringPiece utf8) WARN_UNUSED_RESULT;BASE_EXPORT bool UTF16ToUTF8(const char16_t* src, size_t src_len, std::string* output);BASE_EXPORT std::string UTF16ToUTF8(StringPiece16 utf16) WARN_UNUSED_RESULT;// This converts an ASCII string, typically a hardcoded constant, to a UTF16// string.BASE_EXPORT std::u16string ASCIIToUTF16(StringPiece ascii) WARN_UNUSED_RESULT;// Converts to 7-bit ASCII by truncating. The result must be known to be ASCII// beforehand.BASE_EXPORT std::string UTF16ToASCII(StringPiece16 utf16) WARN_UNUSED_RESULT;#if defined(WCHAR_T_IS_UTF16)// This converts an ASCII string, typically a hardcoded constant, to a wide// string.BASE_EXPORT std::wstring ASCIIToWide(StringPiece ascii) WARN_UNUSED_RESULT;// Converts to 7-bit ASCII by truncating. The result must be known to be ASCII// beforehand.BASE_EXPORT std::string WideToASCII(WStringPiece wide) WARN_UNUSED_RESULT;#endif // defined(WCHAR_T_IS_UTF16)// The conversion functions in this file should not be used to convert string// literals. Instead, the corresponding prefixes (e.g. u"" for UTF16 or L"" for// Wide) should be used. Deleting the overloads here catches these cases at// compile time.template <size_t N>std::u16string WideToUTF16(const wchar_t (&str)[N]) { static_assert(N == 0, "Error: Use the u\"...\" prefix instead."); return std::u16string();}// TODO(crbug.com/1189439): Also disallow passing string constants in tests.#if !defined(UNIT_TEST)template <size_t N>std::u16string ASCIIToUTF16(const char (&str)[N]) { static_assert(N == 0, "Error: Use the u\"...\" prefix instead."); return std::u16string();}// Mutable character arrays are usually only populated during runtime. Continue// to allow this conversion.template <size_t N>std::u16string ASCIIToUTF16(char (&str)[N]) { return ASCIIToUTF16(StringPiece(str));}#endif} // namespace base办法实现// base/strings/utf_string_conversions.ccnamespace base {namespace {constexpr int32_t kErrorCodePoint = 0xFFFD;// Size coefficient ----------------------------------------------------------// The maximum number of codeunits in the destination encoding corresponding to// one codeunit in the source encoding.template <typename SrcChar, typename DestChar>struct SizeCoefficient { static_assert(sizeof(SrcChar) < sizeof(DestChar), "Default case: from a smaller encoding to the bigger one"); // ASCII symbols are encoded by one codeunit in all encodings. static constexpr int value = 1;};template <>struct SizeCoefficient<char16_t, char> { // One UTF-16 codeunit corresponds to at most 3 codeunits in UTF-8. static constexpr int value = 3;};#if defined(WCHAR_T_IS_UTF32)template <>struct SizeCoefficient<wchar_t, char> { // UTF-8 uses at most 4 codeunits per character. static constexpr int value = 4;};template <>struct SizeCoefficient<wchar_t, char16_t> { // UTF-16 uses at most 2 codeunits per character. static constexpr int value = 2;};#endif // defined(WCHAR_T_IS_UTF32)template <typename SrcChar, typename DestChar>constexpr int size_coefficient_v = SizeCoefficient<std::decay_t<SrcChar>, std::decay_t<DestChar>>::value;// UnicodeAppendUnsafe --------------------------------------------------------// Function overloads that write code_point to the output string. Output string// has to have enough space for the codepoint.// Convenience typedef that checks whether the passed in type is integral (i.e.// bool, char, int or their extended versions) and is of the correct size.template <typename Char, size_t N>using EnableIfBitsAre = std::enable_if_t<std::is_integral<Char>::value && CHAR_BIT * sizeof(Char) == N, bool>;template <typename Char, EnableIfBitsAre<Char, 8> = true>void UnicodeAppendUnsafe(Char* out, int32_t* size, uint32_t code_point) { CBU8_APPEND_UNSAFE(out, *size, code_point);}template <typename Char, EnableIfBitsAre<Char, 16> = true>void UnicodeAppendUnsafe(Char* out, int32_t* size, uint32_t code_point) { CBU16_APPEND_UNSAFE(out, *size, code_point);}template <typename Char, EnableIfBitsAre<Char, 32> = true>void UnicodeAppendUnsafe(Char* out, int32_t* size, uint32_t code_point) { out[(*size)++] = code_point;}// DoUTFConversion ------------------------------------------------------------// Main driver of UTFConversion specialized for different Src encodings.// dest has to have enough room for the converted text.template <typename DestChar>bool DoUTFConversion(const char* src, int32_t src_len, DestChar* dest, int32_t* dest_len) { bool success = true; for (int32_t i = 0; i < src_len;) { int32_t code_point; CBU8_NEXT(src, i, src_len, code_point); if (!IsValidCodepoint(code_point)) { success = false; code_point = kErrorCodePoint; } UnicodeAppendUnsafe(dest, dest_len, code_point); } return success;}template <typename DestChar>bool DoUTFConversion(const char16_t* src, int32_t src_len, DestChar* dest, int32_t* dest_len) { bool success = true; auto ConvertSingleChar = [&success](char16_t in) -> int32_t { if (!CBU16_IS_SINGLE(in) || !IsValidCodepoint(in)) { success = false; return kErrorCodePoint; } return in; }; int32_t i = 0; // Always have another symbol in order to avoid checking boundaries in the // middle of the surrogate pair. while (i < src_len - 1) { int32_t code_point; if (CBU16_IS_LEAD(src[i]) && CBU16_IS_TRAIL(src[i + 1])) { code_point = CBU16_GET_SUPPLEMENTARY(src[i], src[i + 1]); if (!IsValidCodepoint(code_point)) { code_point = kErrorCodePoint; success = false; } i += 2; } else { code_point = ConvertSingleChar(src[i]); ++i; } UnicodeAppendUnsafe(dest, dest_len, code_point); } if (i < src_len) UnicodeAppendUnsafe(dest, dest_len, ConvertSingleChar(src[i])); return success;}#if defined(WCHAR_T_IS_UTF32)template <typename DestChar>bool DoUTFConversion(const wchar_t* src, int32_t src_len, DestChar* dest, int32_t* dest_len) { bool success = true; for (int32_t i = 0; i < src_len; ++i) { int32_t code_point = src[i]; if (!IsValidCodepoint(code_point)) { success = false; code_point = kErrorCodePoint; } UnicodeAppendUnsafe(dest, dest_len, code_point); } return success;}#endif // defined(WCHAR_T_IS_UTF32)// UTFConversion --------------------------------------------------------------// Function template for generating all UTF conversions.template <typename InputString, typename DestString>bool UTFConversion(const InputString& src_str, DestString* dest_str) { if (IsStringASCII(src_str)) { dest_str->assign(src_str.begin(), src_str.end()); return true; } dest_str->resize(src_str.length() * size_coefficient_v<typename InputString::value_type, typename DestString::value_type>); // Empty string is ASCII => it OK to call operator[]. auto* dest = &(*dest_str)[0]; // ICU requires 32 bit numbers. int32_t src_len32 = static_cast<int32_t>(src_str.length()); int32_t dest_len32 = 0; bool res = DoUTFConversion(src_str.data(), src_len32, dest, &dest_len32); dest_str->resize(dest_len32); dest_str->shrink_to_fit(); return res;}} // namespace// UTF16 <-> UTF8 --------------------------------------------------------------bool UTF8ToUTF16(const char* src, size_t src_len, std::u16string* output) { return UTFConversion(StringPiece(src, src_len), output);}std::u16string UTF8ToUTF16(StringPiece utf8) { std::u16string ret; // Ignore the success flag of this call, it will do the best it can for // invalid input, which is what we want here. UTF8ToUTF16(utf8.data(), utf8.size(), &ret); return ret;}bool UTF16ToUTF8(const char16_t* src, size_t src_len, std::string* output) { return UTFConversion(StringPiece16(src, src_len), output);}std::string UTF16ToUTF8(StringPiece16 utf16) { std::string ret; // Ignore the success flag of this call, it will do the best it can for // invalid input, which is what we want here. UTF16ToUTF8(utf16.data(), utf16.length(), &ret); return ret;}// UTF-16 <-> Wide -------------------------------------------------------------#if defined(WCHAR_T_IS_UTF16)// When wide == UTF-16 the conversions are a NOP.bool WideToUTF16(const wchar_t* src, size_t src_len, std::u16string* output) { output->assign(src, src + src_len); return true;}std::u16string WideToUTF16(WStringPiece wide) { return std::u16string(wide.begin(), wide.end());}bool UTF16ToWide(const char16_t* src, size_t src_len, std::wstring* output) { output->assign(src, src + src_len); return true;}std::wstring UTF16ToWide(StringPiece16 utf16) { return std::wstring(utf16.begin(), utf16.end());}#elif defined(WCHAR_T_IS_UTF32)bool WideToUTF16(const wchar_t* src, size_t src_len, std::u16string* output) { return UTFConversion(base::WStringPiece(src, src_len), output);}std::u16string WideToUTF16(WStringPiece wide) { std::u16string ret; // Ignore the success flag of this call, it will do the best it can for // invalid input, which is what we want here. WideToUTF16(wide.data(), wide.length(), &ret); return ret;}bool UTF16ToWide(const char16_t* src, size_t src_len, std::wstring* output) { return UTFConversion(StringPiece16(src, src_len), output);}std::wstring UTF16ToWide(StringPiece16 utf16) { std::wstring ret; // Ignore the success flag of this call, it will do the best it can for // invalid input, which is what we want here. UTF16ToWide(utf16.data(), utf16.length(), &ret); return ret;}#endif // defined(WCHAR_T_IS_UTF32)// UTF-8 <-> Wide --------------------------------------------------------------// UTF8ToWide is the same code, regardless of whether wide is 16 or 32 bitsbool UTF8ToWide(const char* src, size_t src_len, std::wstring* output) { return UTFConversion(StringPiece(src, src_len), output);}std::wstring UTF8ToWide(StringPiece utf8) { std::wstring ret; // Ignore the success flag of this call, it will do the best it can for // invalid input, which is what we want here. UTF8ToWide(utf8.data(), utf8.length(), &ret); return ret;}#if defined(WCHAR_T_IS_UTF16)// Easy case since we can use the "utf" versions we already wrote above.bool WideToUTF8(const wchar_t* src, size_t src_len, std::string* output) { return UTF16ToUTF8(as_u16cstr(src), src_len, output);}std::string WideToUTF8(WStringPiece wide) { return UTF16ToUTF8(StringPiece16(as_u16cstr(wide), wide.size()));}#elif defined(WCHAR_T_IS_UTF32)bool WideToUTF8(const wchar_t* src, size_t src_len, std::string* output) { return UTFConversion(WStringPiece(src, src_len), output);}std::string WideToUTF8(WStringPiece wide) { std::string ret; // Ignore the success flag of this call, it will do the best it can for // invalid input, which is what we want here. WideToUTF8(wide.data(), wide.length(), &ret); return ret;}#endif // defined(WCHAR_T_IS_UTF32)std::u16string ASCIIToUTF16(StringPiece ascii) { DCHECK(IsStringASCII(ascii)) << ascii; return std::u16string(ascii.begin(), ascii.end());}std::string UTF16ToASCII(StringPiece16 utf16) { DCHECK(IsStringASCII(utf16)) << UTF16ToUTF8(utf16); return std::string(utf16.begin(), utf16.end());}#if defined(WCHAR_T_IS_UTF16)std::wstring ASCIIToWide(StringPiece ascii) { DCHECK(IsStringASCII(ascii)) << ascii; return std::wstring(ascii.begin(), ascii.end());}std::string WideToASCII(WStringPiece wide) { DCHECK(IsStringASCII(wide)) << wide; return std::string(wide.begin(), wide.end());}#endif // defined(WCHAR_T_IS_UTF16)} // namespace basefuzzer// Entry point for LibFuzzer.extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { base::StringPiece string_piece_input(reinterpret_cast<const char*>(data), size); ignore_result(base::UTF8ToWide(string_piece_input)); base::UTF8ToWide(reinterpret_cast<const char*>(data), size, &output_std_wstring); ignore_result(base::UTF8ToUTF16(string_piece_input)); base::UTF8ToUTF16(reinterpret_cast<const char*>(data), size, &output_string16); // Test for char16_t. if (size % 2 == 0) { base::StringPiece16 string_piece_input16( reinterpret_cast<const char16_t*>(data), size / 2); ignore_result(base::UTF16ToWide(output_string16)); base::UTF16ToWide(reinterpret_cast<const char16_t*>(data), size / 2, &output_std_wstring); ignore_result(base::UTF16ToUTF8(string_piece_input16)); base::UTF16ToUTF8(reinterpret_cast<const char16_t*>(data), size / 2, &output_std_string); } // Test for wchar_t. size_t wchar_t_size = sizeof(wchar_t); if (size % wchar_t_size == 0) { ignore_result(base::WideToUTF8(output_std_wstring)); base::WideToUTF8(reinterpret_cast<const wchar_t*>(data), size / wchar_t_size, &output_std_string); ignore_result(base::WideToUTF16(output_std_wstring)); base::WideToUTF16(reinterpret_cast<const wchar_t*>(data), size / wchar_t_size, &output_string16); } // Test for ASCII. This condition is needed to avoid hitting instant CHECK // failures. if (base::IsStringASCII(string_piece_input)) { output_string16 = base::ASCIIToUTF16(string_piece_input); base::StringPiece16 string_piece_input16(output_string16); ignore_result(base::UTF16ToASCII(string_piece_input16)); } return 0;}

May 17, 2021 · 7 min · jiezi

关于chrome:字符串编码转换

字符串编码转换字符串编码转换波及宽字节表示法与UTF-8表示法之间的转换、宽字节表示法与UTF-16表示法之间的转换、UTF-8表示法与UTF-16表示法之间的转换、UTF-16表示法于ASCII表示法之间的转换、ASCII表示法宽字节表示法之间的转换。 相干文件base/strings/utf\_string\_conversions.h // 字符串编码转换定义base/strings/utf\_string\_conversions.cc // 字符串编码转换实现base/strings/utf\_string\_conversions\_fuzzer.cc // 字符串编码转换实现办法定义// base/strings/utf_string_conversions.h namespace base {// These convert between UTF-8, -16, and -32 strings. They are potentially slow,// so avoid unnecessary conversions. The low-level versions return a boolean// indicating whether the conversion was 100% valid. In this case, it will still// do the best it can and put the result in the output buffer. The versions that// return strings ignore this error and just return the best conversion// possible.BASE_EXPORT bool WideToUTF8(const wchar_t* src, size_t src_len, std::string* output);BASE_EXPORT std::string WideToUTF8(WStringPiece wide) WARN_UNUSED_RESULT;BASE_EXPORT bool UTF8ToWide(const char* src, size_t src_len, std::wstring* output);BASE_EXPORT std::wstring UTF8ToWide(StringPiece utf8) WARN_UNUSED_RESULT;BASE_EXPORT bool WideToUTF16(const wchar_t* src, size_t src_len, std::u16string* output);BASE_EXPORT std::u16string WideToUTF16(WStringPiece wide) WARN_UNUSED_RESULT;BASE_EXPORT bool UTF16ToWide(const char16_t* src, size_t src_len, std::wstring* output);BASE_EXPORT std::wstring UTF16ToWide(StringPiece16 utf16) WARN_UNUSED_RESULT;BASE_EXPORT bool UTF8ToUTF16(const char* src, size_t src_len, std::u16string* output);BASE_EXPORT std::u16string UTF8ToUTF16(StringPiece utf8) WARN_UNUSED_RESULT;BASE_EXPORT bool UTF16ToUTF8(const char16_t* src, size_t src_len, std::string* output);BASE_EXPORT std::string UTF16ToUTF8(StringPiece16 utf16) WARN_UNUSED_RESULT;// This converts an ASCII string, typically a hardcoded constant, to a UTF16// string.BASE_EXPORT std::u16string ASCIIToUTF16(StringPiece ascii) WARN_UNUSED_RESULT;// Converts to 7-bit ASCII by truncating. The result must be known to be ASCII// beforehand.BASE_EXPORT std::string UTF16ToASCII(StringPiece16 utf16) WARN_UNUSED_RESULT;#if defined(WCHAR_T_IS_UTF16)// This converts an ASCII string, typically a hardcoded constant, to a wide// string.BASE_EXPORT std::wstring ASCIIToWide(StringPiece ascii) WARN_UNUSED_RESULT;// Converts to 7-bit ASCII by truncating. The result must be known to be ASCII// beforehand.BASE_EXPORT std::string WideToASCII(WStringPiece wide) WARN_UNUSED_RESULT;#endif // defined(WCHAR_T_IS_UTF16)// The conversion functions in this file should not be used to convert string// literals. Instead, the corresponding prefixes (e.g. u"" for UTF16 or L"" for// Wide) should be used. Deleting the overloads here catches these cases at// compile time.template <size_t N>std::u16string WideToUTF16(const wchar_t (&str)[N]) { static_assert(N == 0, "Error: Use the u\"...\" prefix instead."); return std::u16string();}// TODO(crbug.com/1189439): Also disallow passing string constants in tests.#if !defined(UNIT_TEST)template <size_t N>std::u16string ASCIIToUTF16(const char (&str)[N]) { static_assert(N == 0, "Error: Use the u\"...\" prefix instead."); return std::u16string();}// Mutable character arrays are usually only populated during runtime. Continue// to allow this conversion.template <size_t N>std::u16string ASCIIToUTF16(char (&str)[N]) { return ASCIIToUTF16(StringPiece(str));}#endif} // namespace base办法实现// base/strings/utf_string_conversions.ccnamespace base {namespace {constexpr int32_t kErrorCodePoint = 0xFFFD;// Size coefficient ----------------------------------------------------------// The maximum number of codeunits in the destination encoding corresponding to// one codeunit in the source encoding.template <typename SrcChar, typename DestChar>struct SizeCoefficient { static_assert(sizeof(SrcChar) < sizeof(DestChar), "Default case: from a smaller encoding to the bigger one"); // ASCII symbols are encoded by one codeunit in all encodings. static constexpr int value = 1;};template <>struct SizeCoefficient<char16_t, char> { // One UTF-16 codeunit corresponds to at most 3 codeunits in UTF-8. static constexpr int value = 3;};#if defined(WCHAR_T_IS_UTF32)template <>struct SizeCoefficient<wchar_t, char> { // UTF-8 uses at most 4 codeunits per character. static constexpr int value = 4;};template <>struct SizeCoefficient<wchar_t, char16_t> { // UTF-16 uses at most 2 codeunits per character. static constexpr int value = 2;};#endif // defined(WCHAR_T_IS_UTF32)template <typename SrcChar, typename DestChar>constexpr int size_coefficient_v = SizeCoefficient<std::decay_t<SrcChar>, std::decay_t<DestChar>>::value;// UnicodeAppendUnsafe --------------------------------------------------------// Function overloads that write code_point to the output string. Output string// has to have enough space for the codepoint.// Convenience typedef that checks whether the passed in type is integral (i.e.// bool, char, int or their extended versions) and is of the correct size.template <typename Char, size_t N>using EnableIfBitsAre = std::enable_if_t<std::is_integral<Char>::value && CHAR_BIT * sizeof(Char) == N, bool>;template <typename Char, EnableIfBitsAre<Char, 8> = true>void UnicodeAppendUnsafe(Char* out, int32_t* size, uint32_t code_point) { CBU8_APPEND_UNSAFE(out, *size, code_point);}template <typename Char, EnableIfBitsAre<Char, 16> = true>void UnicodeAppendUnsafe(Char* out, int32_t* size, uint32_t code_point) { CBU16_APPEND_UNSAFE(out, *size, code_point);}template <typename Char, EnableIfBitsAre<Char, 32> = true>void UnicodeAppendUnsafe(Char* out, int32_t* size, uint32_t code_point) { out[(*size)++] = code_point;}// DoUTFConversion ------------------------------------------------------------// Main driver of UTFConversion specialized for different Src encodings.// dest has to have enough room for the converted text.template <typename DestChar>bool DoUTFConversion(const char* src, int32_t src_len, DestChar* dest, int32_t* dest_len) { bool success = true; for (int32_t i = 0; i < src_len;) { int32_t code_point; CBU8_NEXT(src, i, src_len, code_point); if (!IsValidCodepoint(code_point)) { success = false; code_point = kErrorCodePoint; } UnicodeAppendUnsafe(dest, dest_len, code_point); } return success;}template <typename DestChar>bool DoUTFConversion(const char16_t* src, int32_t src_len, DestChar* dest, int32_t* dest_len) { bool success = true; auto ConvertSingleChar = [&success](char16_t in) -> int32_t { if (!CBU16_IS_SINGLE(in) || !IsValidCodepoint(in)) { success = false; return kErrorCodePoint; } return in; }; int32_t i = 0; // Always have another symbol in order to avoid checking boundaries in the // middle of the surrogate pair. while (i < src_len - 1) { int32_t code_point; if (CBU16_IS_LEAD(src[i]) && CBU16_IS_TRAIL(src[i + 1])) { code_point = CBU16_GET_SUPPLEMENTARY(src[i], src[i + 1]); if (!IsValidCodepoint(code_point)) { code_point = kErrorCodePoint; success = false; } i += 2; } else { code_point = ConvertSingleChar(src[i]); ++i; } UnicodeAppendUnsafe(dest, dest_len, code_point); } if (i < src_len) UnicodeAppendUnsafe(dest, dest_len, ConvertSingleChar(src[i])); return success;}#if defined(WCHAR_T_IS_UTF32)template <typename DestChar>bool DoUTFConversion(const wchar_t* src, int32_t src_len, DestChar* dest, int32_t* dest_len) { bool success = true; for (int32_t i = 0; i < src_len; ++i) { int32_t code_point = src[i]; if (!IsValidCodepoint(code_point)) { success = false; code_point = kErrorCodePoint; } UnicodeAppendUnsafe(dest, dest_len, code_point); } return success;}#endif // defined(WCHAR_T_IS_UTF32)// UTFConversion --------------------------------------------------------------// Function template for generating all UTF conversions.template <typename InputString, typename DestString>bool UTFConversion(const InputString& src_str, DestString* dest_str) { if (IsStringASCII(src_str)) { dest_str->assign(src_str.begin(), src_str.end()); return true; } dest_str->resize(src_str.length() * size_coefficient_v<typename InputString::value_type, typename DestString::value_type>); // Empty string is ASCII => it OK to call operator[]. auto* dest = &(*dest_str)[0]; // ICU requires 32 bit numbers. int32_t src_len32 = static_cast<int32_t>(src_str.length()); int32_t dest_len32 = 0; bool res = DoUTFConversion(src_str.data(), src_len32, dest, &dest_len32); dest_str->resize(dest_len32); dest_str->shrink_to_fit(); return res;}} // namespace// UTF16 <-> UTF8 --------------------------------------------------------------bool UTF8ToUTF16(const char* src, size_t src_len, std::u16string* output) { return UTFConversion(StringPiece(src, src_len), output);}std::u16string UTF8ToUTF16(StringPiece utf8) { std::u16string ret; // Ignore the success flag of this call, it will do the best it can for // invalid input, which is what we want here. UTF8ToUTF16(utf8.data(), utf8.size(), &ret); return ret;}bool UTF16ToUTF8(const char16_t* src, size_t src_len, std::string* output) { return UTFConversion(StringPiece16(src, src_len), output);}std::string UTF16ToUTF8(StringPiece16 utf16) { std::string ret; // Ignore the success flag of this call, it will do the best it can for // invalid input, which is what we want here. UTF16ToUTF8(utf16.data(), utf16.length(), &ret); return ret;}// UTF-16 <-> Wide -------------------------------------------------------------#if defined(WCHAR_T_IS_UTF16)// When wide == UTF-16 the conversions are a NOP.bool WideToUTF16(const wchar_t* src, size_t src_len, std::u16string* output) { output->assign(src, src + src_len); return true;}std::u16string WideToUTF16(WStringPiece wide) { return std::u16string(wide.begin(), wide.end());}bool UTF16ToWide(const char16_t* src, size_t src_len, std::wstring* output) { output->assign(src, src + src_len); return true;}std::wstring UTF16ToWide(StringPiece16 utf16) { return std::wstring(utf16.begin(), utf16.end());}#elif defined(WCHAR_T_IS_UTF32)bool WideToUTF16(const wchar_t* src, size_t src_len, std::u16string* output) { return UTFConversion(base::WStringPiece(src, src_len), output);}std::u16string WideToUTF16(WStringPiece wide) { std::u16string ret; // Ignore the success flag of this call, it will do the best it can for // invalid input, which is what we want here. WideToUTF16(wide.data(), wide.length(), &ret); return ret;}bool UTF16ToWide(const char16_t* src, size_t src_len, std::wstring* output) { return UTFConversion(StringPiece16(src, src_len), output);}std::wstring UTF16ToWide(StringPiece16 utf16) { std::wstring ret; // Ignore the success flag of this call, it will do the best it can for // invalid input, which is what we want here. UTF16ToWide(utf16.data(), utf16.length(), &ret); return ret;}#endif // defined(WCHAR_T_IS_UTF32)// UTF-8 <-> Wide --------------------------------------------------------------// UTF8ToWide is the same code, regardless of whether wide is 16 or 32 bitsbool UTF8ToWide(const char* src, size_t src_len, std::wstring* output) { return UTFConversion(StringPiece(src, src_len), output);}std::wstring UTF8ToWide(StringPiece utf8) { std::wstring ret; // Ignore the success flag of this call, it will do the best it can for // invalid input, which is what we want here. UTF8ToWide(utf8.data(), utf8.length(), &ret); return ret;}#if defined(WCHAR_T_IS_UTF16)// Easy case since we can use the "utf" versions we already wrote above.bool WideToUTF8(const wchar_t* src, size_t src_len, std::string* output) { return UTF16ToUTF8(as_u16cstr(src), src_len, output);}std::string WideToUTF8(WStringPiece wide) { return UTF16ToUTF8(StringPiece16(as_u16cstr(wide), wide.size()));}#elif defined(WCHAR_T_IS_UTF32)bool WideToUTF8(const wchar_t* src, size_t src_len, std::string* output) { return UTFConversion(WStringPiece(src, src_len), output);}std::string WideToUTF8(WStringPiece wide) { std::string ret; // Ignore the success flag of this call, it will do the best it can for // invalid input, which is what we want here. WideToUTF8(wide.data(), wide.length(), &ret); return ret;}#endif // defined(WCHAR_T_IS_UTF32)std::u16string ASCIIToUTF16(StringPiece ascii) { DCHECK(IsStringASCII(ascii)) << ascii; return std::u16string(ascii.begin(), ascii.end());}std::string UTF16ToASCII(StringPiece16 utf16) { DCHECK(IsStringASCII(utf16)) << UTF16ToUTF8(utf16); return std::string(utf16.begin(), utf16.end());}#if defined(WCHAR_T_IS_UTF16)std::wstring ASCIIToWide(StringPiece ascii) { DCHECK(IsStringASCII(ascii)) << ascii; return std::wstring(ascii.begin(), ascii.end());}std::string WideToASCII(WStringPiece wide) { DCHECK(IsStringASCII(wide)) << wide; return std::string(wide.begin(), wide.end());}#endif // defined(WCHAR_T_IS_UTF16)} // namespace basefuzzer// Entry point for LibFuzzer.extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { base::StringPiece string_piece_input(reinterpret_cast<const char*>(data), size); ignore_result(base::UTF8ToWide(string_piece_input)); base::UTF8ToWide(reinterpret_cast<const char*>(data), size, &output_std_wstring); ignore_result(base::UTF8ToUTF16(string_piece_input)); base::UTF8ToUTF16(reinterpret_cast<const char*>(data), size, &output_string16); // Test for char16_t. if (size % 2 == 0) { base::StringPiece16 string_piece_input16( reinterpret_cast<const char16_t*>(data), size / 2); ignore_result(base::UTF16ToWide(output_string16)); base::UTF16ToWide(reinterpret_cast<const char16_t*>(data), size / 2, &output_std_wstring); ignore_result(base::UTF16ToUTF8(string_piece_input16)); base::UTF16ToUTF8(reinterpret_cast<const char16_t*>(data), size / 2, &output_std_string); } // Test for wchar_t. size_t wchar_t_size = sizeof(wchar_t); if (size % wchar_t_size == 0) { ignore_result(base::WideToUTF8(output_std_wstring)); base::WideToUTF8(reinterpret_cast<const wchar_t*>(data), size / wchar_t_size, &output_std_string); ignore_result(base::WideToUTF16(output_std_wstring)); base::WideToUTF16(reinterpret_cast<const wchar_t*>(data), size / wchar_t_size, &output_string16); } // Test for ASCII. This condition is needed to avoid hitting instant CHECK // failures. if (base::IsStringASCII(string_piece_input)) { output_string16 = base::ASCIIToUTF16(string_piece_input); base::StringPiece16 string_piece_input16(output_string16); ignore_result(base::UTF16ToASCII(string_piece_input16)); } return 0;}

May 16, 2021 · 7 min · jiezi

关于chrome:关闭Chrome-右下角-可恶的广告-cncompbscom

敞开Chrome 右下角 可恶的广告 - cn.compbs.com 就是这个,忽然间每天都要弹出来几次,有的还是流氓的低俗广告,甚是厌恶 谷歌浏览器,关上设置->隐衷设置和安全性(chrome://settings/content/notifications) 给他禁止掉或者删除掉,如果有拉黑性能就拉黑,烦人的破站

May 10, 2021 · 1 min · jiezi

关于chrome:CSCIGA2250-Programming-Assignment

Programming Assignment #4 (Lab 4): IO Scheduling Professor Hubertus FrankeClass CSCI-GA.2250-001/002 Spring2021In this lab you implement/simulate the scheduling and optimization of I/O operations. Applications submit their IO requeststo the IO subsystem (potentially via the filesystem and page-cache), where they are maintained in an IO-queue until the diskdevice is ready for servicing another request. The IO-scheduler then selects a request from the IO-queue and submits it to thedisk device. This selection is commonly known as the strategy() routine in operating systems. On completion, anotherrequest can be taken from the IO-queue and submitted to the disk. The scheduling policies will allow for some optimizationas to reduce disk head movement or overall wait time in the system. The schedulers to be implemented are FIFO (i), SSTF (j),LOOK (s), CLOOK (c), and FLOOK (f) (the letters in bracket define which parameter must be given in the –s program flag).You are to implement these different IO-schedulers in C or C++ and submit the source code, which we will compile and run.Your submission must contain a Makefile so we can run on linserv*.cims.nyu.edu (and please at least test there as well).Invocation is a follows:./iosched –s<schedalgo> [options] <inputfile> // options are -v -q -f (see below)The input file is structured as follows: Lines starting with ‘#’ are comment lines and should be ignored.Any other line describes an IO operation where the 1st integer is the time step at which the IO operation is issued and the 2ndinteger is the track that is accesses. Since IO operation latencies are largely dictated by seek delay (i.e. moving the head to thecorrect track), we ignore rotational and transfer delays for simplicity. The inputs are well formed. ...

April 25, 2021 · 6 min · jiezi

关于javascript:使用chrome工具进行内存泄漏排查

发现问题:找到疑似操作Chrome Performance 排查 点击开始录制 ,在页面上进行操作,之后察看堆内存应用趋势,尝试屡次如察看到为上涨趋势时就有可能是内存透露(并不能认定肯定是内存透露,有可能是内存还没有开释),如果呈现这种状况咱们就要应用 memory 看板进行进一步的剖析 留神点:在每次开始和完结前都要点击垃圾回收 Performance monitor 看板 第二种形式是应用 performance monitor 面板进行排查, 能够一边操作一边查看performance monitor 面板上内存的应用趋势,如果内存呈现上涨趋势的状况也有可能是呈现内存透露 剖析内存快照:找到问题起因Memory 看板 切换到memory 看板点击截取快照生成快照 1操作疑似透露的操作 再生成快照 2切换到comparsion(比照试图)察看 Delta 列察看增长较大的对象,可能存在内存透露的问题反复以上的操作,直到定位到具体的起因Dom 树援用内存透露问题排查 抉择 summary 试图,搜寻 detached ,搜寻到局部的dom曾经销毁,然而还被 js 援用这部分会导致内存透露 辨认 js 对象内存透露 录制时,请留神“调配时间轴”上是否有蓝色条状显示, 这些蓝色条示意新的内存调配,这些新的内存调配是内存透露的对象。 抉择特定的区域排查透露的对象。 术语解释试图 Summary:摘要视图 Comparison:比照视图,与其它快照比照,看增、删、Delta数量及内存大小 Containment:鸟瞰视图,自顶向下看堆的状况,根节点包含window对象,GC root,原生对象等等 列头 Shallow Size   : 对象自身占用的内存Retained Size : 对象自身及其援用总共占用的内存Distance :以后对象到根的援用层级间隔Alloc. Size : 新调配的内存Freed  Size : 开释的内存 https://developer.chrome.com/...

April 23, 2021 · 1 min · jiezi

关于javascript:Chrome-浏览器多进程架构-3个-必会知识点

本文全长 20 分钟 , 市场价值¥ xxx9.9 元, 倡议在工夫富余下进行具体浏览。 ️ 读本章节内容中,带着以下三个问题进行浏览,更加有助于了解 Problem1 : 关上一个页面须要启动过程的配比是什么?<br/>Problem2 : 为何浏览器要应用多过程架构设计?<br/>Problem3 : 多过程架构为何仍会因为单页面卡死导致所有页面解体?<br/> 如果想要设计高性能 Web 利用,还是要优化现有的 Web 利用,<br/>都须要理解浏览器中的网络流程、页面渲染过程,JavaScript 执行流程,以及 Web 平安实践。 在本文中,所有的剖析都是基于 Chrome 浏览器的。<br/>因为 Chrome、微软的 Edge 以及国内的大部分支流浏览器,都是基于 Chromium 二次开发而来;<br/>再加上 Chrome 是目前世界上应用频率较高的浏览器,所以 Chrome 具备代表性。 关上一个页面须要启动多少过程?在开始之前,咱们一起看下,Chrome 关上一个页面须要启动多少过程?你能够点击 Chrome 浏览器右上角的“选项”菜单,抉择“更多工具”子菜单,点击“工作管理器”,这将关上 Chrome 的工作管理器的窗口,如下图: 那关上一个页面须要启动 7 个过程?其实不是的。 图片里的扩大程序:Dark Reader 这个是我本机装置的实用于任何网站的光明主题扩大程序,所以也占用了过程;<br/>实用程序:Audio Service 是用于解决音频的,也并非是肯定要应用的。<br/>Storage Service 即便页面未启用 WebStorage, 该过程也会启动并取得内存空间调配, 不过此时 CPU 占用为 0.0 ️ 所以关上一个页面根本要应用到的过程配比到底是什么样的?( ⌛️ 请容许我先将这个问题挂起)在解答这个问题之前,咱们须要理解一下过程的概念,因为好多人容易把过程和线程的概念混同,<br/>所以这里就将这两个概念以及它们之间的关系一并解说下。 理解过程和线程在介绍过程和线程之前,须要先解说下什么是并行处理。<br/>如果你了解了并行处理的概念,那么再了解过程和线程之间的关系就会变得轻松许多。<br/> 计算机中的并行处理就是同一时刻解决多个工作。<br/><br/> 举个例子:咱们要计算上面这三个表达式的值,并显示出后果<br/> ...

April 22, 2021 · 2 min · jiezi

关于javascript:了解V8二类型转换V8是怎么实现12的

各位小伙伴们好,明天咱们来聊一聊JavaScript 中的“类型零碎”。 然而在开始之前呢咱们能够先思考一个简略的表达式,那就是在 JavaScript 中,“1+‘2’等于多少?” 其实这相当于是在问,在 JavaScript 中,让数字和字符串相加是会报错,还是能够正确执行。 如果能正确执行,那么后果是等于数字 3,还是字符串“3”,还是字符串“12”呢? 如果你尝试用一些其余语言执行数字了字符串相加,会是什么杨的后果呢。 比如说用 Python 应用数字和字符串进行相加操作,则会间接返回一个执行谬误,谬误提醒是这样的: >>>1+'2' Traceback (most recent call last): File "&lt;stdin&gt;", line 1, in &lt;module&gt; TypeError: unsupported operand type(s) for +: 'int' and 'str'然而在 JavaScript 中执行这段表达式,却是能够返回一个后果的,最终返回的后果是字符串“12”。 那么为什么同样的表达式,在 Python 和 JavaScript 中执行为什么会有不同的后果?为什么在 JavaScript 中执行,输入的是字符串“12”,不是数字 3 或者字符串“3”呢?什么是类型零碎 (Type System)?在上边的表达式中,波及到了两种不同类型的数据的相加。要想理清以上两个问题,咱们就须要晓得类型的概念,以及 JavaScript 操作类型的策略。 对机器语言来说,所有的数据都是一堆二进制代码,CPU 解决这些数据的时候,并没有类型的概念,CPU 所做的仅仅是挪动数据,比方对其进行移位,相加或相乘。 而在高级语言中,咱们都会为操作的数据赋予指定的类型,类型能够确认一个值或者一组值具备特定的意义和目标。所以,类型是高级语言中的概念。 在 JavaScript 中,你能够这样定义变量: var num = 100 # 赋值整型变量 let miles = 1000.0 # 浮点型 const name = "John" # 字符串V8 是怎么执行加法操作的?理解了类型零碎,接下来咱们就能够来看看 V8 是怎么解决 1+“2”的了。当有两个值相加的时候,比方: ...

April 22, 2021 · 2 min · jiezi

关于前端:了解V8一-V8采用了哪些策略提升了对象属性的访问速度

JavaScript 语言的角度来看,JavaScript 对象像一个字典,字符串作为键名,任意对象能够作为键值,能够通过键名读写键值。 然而在 V8 实现对象存储时,并没有齐全采纳字典的存储形式,这次要是出于性能的考量。因为字典是非线性的数据结构,查问效率会低于线性的数据结构,V8 为了晋升存储和查找效率,采纳了一套简单的存储策略。 明天咱们理解一下v8为了晋升对象的拜访性能都采纳了那些策略 首先咱们来剖析一下下边的这段代码 function Foo() { this[100] = 'test-100' this[1] = 'test-1' this["B"] = 'bar-B' this[50] = 'test-50' this[9] = 'test-9' this[8] = 'test-8' this[3] = 'test-3' this[5] = 'test-5' this["A"] = 'bar-A' this["C"] = 'bar-C'}var bar = new Foo()for(key in bar){ console.log(`index:${key} value:${bar[key]}`)}在下面这段代码中,咱们利用构造函数 Foo 创立了一个 bar 对象,在构造函数中,咱们给 bar 对象设置了很多属性,包含了数字属性和字符串属性,而后咱们枚举进去了 bar 对象中所有的属性,并将其一一打印进去,上面就是执行这段代码所打印进去的后果: index:1 value:test-1index:3 value:test-3index:5 value:test-5index:8 value:test-8index:9 value:test-9index:50 value:test-50index:100 value:test-100index:B value:bar-Bindex:A value:bar-Aindex:C value:bar-C察看这段打印进去的数据,咱们发现打印进去的属性程序并不是咱们设置的程序,咱们设置属性的时候是乱序设置的,比方开始先设置 100,而后又设置了 1,然而输入的内容却十分法则,总的来说体现在以下两点: ...

April 22, 2021 · 4 min · jiezi

关于chrome:Chrome-浏览器扩展-Night-Eye

我以前始终应用一款叫做 Care your Eyes 的 Chrome 浏览器扩大,能将任何网站背景设置成彩色。 最近我的 Chrome 降级到下列这个版本后,发现这个扩大无奈工作了: Version 89.0.4389.114 (Official Build) (64-bit) 于是更换了一个名叫 Night Eye 的扩大。在 Chrome 扩大商店下载安装之后,发现其有三个月的试用期。 我平时常常用的知乎和 CSDN,未开启 night 模式时默认的成果: 应用 Night Eye 开启深色模式的成果: 据这个帖子介绍,Night Eye 1.0 版本就破费了 10 个月的工夫来开发。 https://zhuanlan.zhihu.com/p/... 更多Jerry的原创文章,尽在:"汪子熙":

April 18, 2021 · 1 min · jiezi

关于chrome:查看页面加载性能从未如此简单

Chrome插件地址:Performance Assistant 源码:Github地址 背景页面加载性能是前端工程师对页面关注最多的问题之一,对前端我的项目做了加载优化,想查看加载性能直观数据,比方 onload 触发工夫、TTI、FCP 等等,个别是利用开发者工具的 Performance 或者 Lighthouse 来达到目标,或者对页面注入相似上面的性能统计代码,来打印或者上报加载性能数据。而这些形式利用现有工具不够快捷,监控代码要嘛入侵代码或要嘛须要集成进前端脚手架,对于咱们简略查看页面加载数据的诉求有些大费周章的感觉。所以搞了一个 Chrome 插件,页面刷新之后间接就能查看加载性能数据,简略高效。 // 计算性能指标(() => { const createConsole = (desc, val) => console.log( `%c${desc}`, 'color:#fff;background:red;padding:2px 6px;border-radius:3px;', val); window.addEventListener('load', () => { const timing = performance.timing; createConsole('DNS 解析耗时', timing.domainLookupEnd - timing.domainLookupStart); createConsole('TCP连贯耗时', timing.connectEnd - timing.connectStart); createConsole('网络申请耗时', timing.responseStart - timing.requestStart); createConsole('数据传输耗时', timing.responseEnd - timing.requestStart); createConsole('页面首次渲染工夫', timing.responseEnd - timing.navigationStart); createConsole('首次可交互工夫', timing.domInteractive - timing.navigationStart); createConsole('DOM解析耗时', timing.domInteractive - timing.responseEnd); createConsole('DOM构建耗时', timing.domComplete - timing.domInteractive); createConsole('HTML 加载实现,DOM Ready', timing.domContentLoadedEventEnd - timing.navigationStart); createConsole('页面齐全加载耗时', timing.loadEventStart - timing.navigationStart); });})();对于页面加载过程中波及各个事件节点不分明的同学能够看下 W3C 的官网介绍《Navigation Timing》,不想看英文的同学能够看下《Web 性能优化-首屏和白屏工夫》这篇文章,对工夫节点的形容很具体。具体的就是上面这张图: ...

April 18, 2021 · 1 min · jiezi

关于前端:谷歌插件开发探索及其应用

前言之前笔者始终想理解一些对于谷歌插件的相干常识,通过这个谷歌插件也能够更好的意识到这个谷歌的调试工具,正好最近须要进行分享,这两个星期去学习和理解了谷歌插件,而后写了这一篇文章,把自己所理解的和一些思考点写了下来。同时,也想着能够应用谷歌插件去写一些小工具,既学习了新的货色,又有肯定的趣味性。当然,因为工夫的起因,如果笔者对于这一块的意识有不对的中央,欢送批评指正~ 什么是谷歌插件谷歌插件,全名谷歌浏览器扩大程序。那什么是谷歌浏览器扩大程序,官网阐明如下: 扩大程序容许您为 Chrome 浏览器减少性能,而不须要深入研究本机代码。您能够应用您在网页开发中曾经很相熟的核心技术(HTML、CSS 与 JavaScript)为 Chrome 浏览器创立新的扩大程序。有纳闷的同学会问了,为什么人家还叫谷歌插件,那这就正如鲁迅所说的那句话:世上本没有路,走的人多了,也就有路了。谷歌浏览器扩大程序原本也不是谷歌插件,谷歌插件应该是浏览器更为底层的货色,奈何叫的人太多了,所以本文也应用谷歌插件来统称谷歌浏览器扩大程序。 根本应用上面先介绍一下谷歌插件的次要组成部分,因为目前谷歌插件应用比拟广泛的版本为 2.0 版本,所有以下都是基于 2.0 版本进行应用阐明,3.0 版本相较于 2.0 版本更为简便,有趣味的同学能够点击文章开端处的链接理解更多相干常识。 配置文件谷歌插件的外围文件就是配置文件--manifest.json(清单)文件。其中,manifest.json 文件最根本的 Api 如下: { "name": "chrome extension", "version": "1.0.0", "manifest_version": 2, "description": "A litlle chrome extension demo"}次要是蕴含所写谷歌插件的名称,版本,以及相干形容,其中 manifest_version 示意清单文件版本。manifest.json 作为谷歌插件的外围局部,笔者认为该文件对插件来说就相当于一个入口配置文件,开发只须要在这个文件通过配置相应的 js,调用谷歌浏览器提供的 Api,来达到欠缺这个插件的目标。 根本应用Api在清单文件中还有很多 Api 就不一一列举了,上面只介绍几个笔者认为比拟重要的几个 Api,通过以下几个 Api 能够使得读者对于谷歌插件的开发过程有一个大略的意识。 browser_action{ ... "browser_action": { "default_icon": { "16": "images/get_started16.png", "32": "images/get_started32.png" }, "default_title": "谷歌划词翻译", "default_popup": "popup.html" }, ...}browser_action 可设置浏览器右上角的图标,名称。default_popup 可配置点击图标后会呈现的一个小窗口,这里能够做一些临时性的操作。 permissions{ ... "permissions": [ "activeTab", "storage", "tabs", "contextMenus" ], ...}permissions 可配置谷歌插件权限申请,如 contextMenus(右键菜单), tabs(标签),storage(插件本地存储)。 ...

April 12, 2021 · 3 min · jiezi

关于前端:CSS-浮动-float-小结

引子在保护一些我的项目的时候,发现不少中央用 float 来进行布局,晓得这个属性的作用成果,也晓得怎么解决相干的问题,但就是不能进一步说出一个所以然来,就整顿一下了。 OriginMy GitHub约定这里是为了了解 float 相干的问题和解决办法,不去比拟它们的优劣和兼容性,要置信将来是越来越美妙的。根本的 html 构造如下: <div class="float-parent"> <div class="float-ele fl"></div></div>以下所讲示例页面:CSS浮动float相干初解示例 手机端浏览 浮动的用处浮动设计的初衷,是为了实现文本盘绕成果。在一些教程外面,对于浮动的介绍没有强调这个,而是讲如何利用这个属性的作用,去实现一些所谓“乏味”的成果。尽管拓展了思路,但感觉并没有用的适合。 浮动的介绍W3C 文档外面说的很简洁:这个属性指定一个盒子浮动到右边、左边还是不浮动。上面是摘取过去的根本个性。 Value: left | right | none | inheritInitial: noneApplies to: all,but see 9.7Inherited: no上面就是相干阐明和一些留神项。 重要的认知浮动使元素从失常的文档流中移除,脱离了失常的文档流。而后向左或者向右平移,始终挪动直到碰到了所处的容器的边界,或者碰到另外一个浮动的元素。 值的作用left :元素会产生一个块级盒子向左浮动,失常的文档流会从这个盒子的左边和顶部开始。right :跟 left 属性值相似,只是元素产生的块级盒子向右浮动,失常的文档流会从这个盒子的右边和顶部开始。none :这个盒子不浮动。display, position 和 float 之间的关系屡次看到有人把这些属性写在一起,感觉是在用试错的心理写 CSS 。以下状况示例页面:display、position 和 float 之间的关系示例 。精力有限,规定利用下只试了局部取值状况。 这三个属性影响盒子产生和布局,它们相互影响有以下的程序规定判断: 如果 display 的属性值为 none ,那么 position 和 float 属性不会利用。这种状况不会产生盒子。否则,如果 position 的指定值为 absolute 或 fixed ,这个盒子会是相对定位,float 的计算值会取 none ,display 的取值规定依照上面的表格所示。这个盒子的地位取决于 top ,right ,bottom ,left 属性和这个盒子的蕴含块。否则,如果 float 指定了 none 之外的值,这个盒子就会浮动,并且 display 取值规定依照上面的表格所示。否则,如果这个元素是根元素,display 取值规定依照上面的表格所示。但在CSS2.2 有一种状况例外,指定为 list-item 的值变成计算值为 block 或 list-item 时,它的值未定义。否则,剩下的 display 属性值依照指定的值利用。指定的值计算值inline-tabletableinline, table-row-group, table-column, table-column-group, table-header-group, table-footer-group, table-row, table-cell, table-caption, inline-blockblockotherssame as specified由以上的规定可知,将这些属性写一起,有些时候并不会起作用。对于不相熟的人反而会造成不必要的困惑。 ...

April 5, 2021 · 1 min · jiezi

关于css:前端面试每日-31-第719天

明天的知识点 (2021.04.04) —— 第719天 (我也要出题)[html] 文件抉择框如何多选文件?[css] 画一个不停收回不同光的球[js] 在js中整数超出平安范畴怎么办?[软技能] 说说你对原码、反码和补码的了解《论语》,曾子曰:“吾日三省吾身”(我每天屡次检查本人)。前端面试每日3+1题,以面试题来驱动学习,每天提高一点!让致力成为一种习惯,让奋斗成为一种享受!置信 保持 的力量!!! 欢送在 Issues 和敌人们一起探讨学习! 我的项目地址:前端面试每日3+1【举荐】欢送跟 jsliang 一起折腾前端,零碎整顿前端常识,目前正在折腾 LeetCode,打算买通算法与数据结构的任督二脉。GitHub 地址 微信公众号欢送大家前来探讨,如果感觉对你的学习有肯定的帮忙,欢送点个Star, 同时欢送微信扫码关注 前端剑解 公众号,并退出 “前端学习每日3+1” 微信群互相交换(点击公众号的菜单:交换)。 学习不打烊,充电加油只为遇到更好的本人,365天无节假日,每天早上5点纯手工公布面试题(死磕本人,愉悦大家)。心愿大家在这虚夸的前端圈里,放弃沉着,保持每天花20分钟来学习与思考。在这变幻无穷,类库层出不穷的前端,倡议大家不要等到找工作时,才狂刷题,提倡每日学习!(不忘初心,html、css、javascript才是基石!)欢送大家到Issues交换,激励PR,感激Star,大家有啥好的倡议能够加我微信一起交换探讨! 心愿大家每日去学习与思考,这才达到来这里的目标!!!(不要为了谁而来,要为本人而来!)交换探讨欢送大家前来探讨,如果感觉对你的学习有肯定的帮忙,欢送点个[Star]

April 4, 2021 · 1 min · jiezi

关于javascript:89版本的chrome不支持less-deep样式穿透

问题chrome版本号89.0.4389.90,不反对less的/deep/款式穿透解决既要关照以前的版本,又要兼容新版本,倡议写两种css款式 .main{ .el-dialog__headerbtn{ top:-5px!important; right:0px!important; } /deep/.el-dialog__headerbtn{ top:-5px!important; right:0px!important; }}留神:/deep/只实用less,sass用::v-deep留神:/deep/的最好放在没/deep/的前面 89版本的chrome不反对less deep款式穿透

March 29, 2021 · 1 min · jiezi

关于chrome:浏览器存储那些事

前言随着挪动网络的倒退与演变,咱们手机上当初除了有原生 App,还能跑“WebApp”——它即开即用,用完即走。一个优良的 WebApp 甚至能够领有和原生 App 媲美的性能和体验。WebApp 优异的性能体现,有一部分起因要归功于浏览器存储技术的晋升。cookie存储数据的性能曾经很难满足开发所需,逐步被Web Storage、IndexedDB所取代,本文将介绍这几种存储形式的差别和优缺点。 一、cookie1.cookie的起源cookie 的本职工作并非本地存储,而是“维持状态”。因为HTTP协定是无状态的,HTTP协定本身不对申请和响应之间的通信状态进行保留,艰深来说,服务器不晓得用户上一次做了什么,这重大妨碍了交互式Web应用程序的实现。在典型的网上购物场景中,用户浏览了几个页面,买了一盒饼干和两瓶饮料。最初结帐时,因为HTTP的无状态性,不通过额定的伎俩,服务器并不知道用户到底买了什么,于是就诞生了cookie。它就是用来绕开HTTP的无状态性的“额定伎俩”之一。服务器能够设置或读取cookie中蕴含信息,借此保护用户跟服务器会话中的状态。 在方才的购物场景中,当用户选购了第一项商品,服务器在向用户发送网页的同时,还发送了一段cookie,记录着那项商品的信息。当用户拜访另一个页面,浏览器会把cookie发送给服务器,于是服务器晓得他之前选购了什么。用户持续选购饮料,服务器就在原来那段Cookie里追加新的商品信息。结帐时,服务器读取发送来的cookie就行了。 2.什么是cookiecookie指某些网站为了分别用户身份而贮存在用户本地终端上的数据(通常通过加密)。 cookie是服务端生成,客户端进行保护和存储,存储在内存或者磁盘中。通过cookie,能够让服务器晓得申请是起源哪个客户端,就能够进行客户端状态的保护,比方登陆后刷新,申请头就会携带登陆时response header中的Set-Cookie,Web服务器接到申请时也能读出cookie的值,依据cookie值的内容就能够判断和复原一些用户的信息状态。 简而言之,cookie 使基于无状态的HTTP协定记录稳固的状态信息成为了可能。 cookie 次要用于以下三个方面: 会话状态治理(如用户登录状态、购物车、游戏分数或其它须要记录的信息)个性化设置(如用户自定义设置、主题等)浏览器行为跟踪(如跟踪剖析用户行为等)3.cookie的原理及其形成 第一次拜访网站的时候,浏览器发出请求,服务器端生成 cookie在响应中通过Set-Cookie头部告知客户端(容许多个Set-Cookie头部传递多个值),客户端失去 cookie后,后续申请都会主动将 cookie头部携带至申请中发送给服务器(见上面例子),另外,cookie的过期工夫、域、门路、有效期、实用站点都能够依据须要来指定。 // 一个HTTP响应:HTTP/1.1 200 OKContent-type: text/htmlSet-Cookie: name=valueOther-header: other-header-value这个HTTP响应会设置一个名为"name",值为"value"的cookie。名和值在发送时都会通过URL编码。浏览器会存储这些会话信息,并在之后的每个申请中都会通过HTTP头部cookie再将它们发回服务器,比方: GET /index.jsl HTTP/1.1Cookie: name=valueOther-header: other-header-valuecookie在浏览器中是由以下参数形成的: name:惟一标识cookie的名称。cookie名不辨别大小写,因而myCookie和MyCookie是同一个名称。不过,实际中最好将cookie名当成辨别大小写来看待,因为一些服务器软件可能这样看待它们。cookie名必须通过URL编码。value:存储在cookie里的字符串值。这个值必须通过URL编码。Domain:cookie无效的域。发送到这个域的所有申请都会蕴含对应的cookie。如果不指定,默认为文档起源(由协定、域名和端口独特定义),不蕴含子域名。如果指定了Domain,则个别蕴含子域名。因而,指定 Domain 比省略它的限度要少。然而,当子域须要共享无关用户的信息时,这可能会有所帮忙。例如,如果设置 Domain=mozilla.org,则 Cookie 也蕴含在子域名中(如developer.mozilla.org)。Path:申请URL中蕴含这个门路才会把cookie发送到服务器。// 例如,设置 Path=/docs,则以下地址都会匹配:/docs/docs/Web//docs/Web/HTTPExpires/Max-Age:设置cookie过期工夫(Expires)或有效期(Max-Age)(即什么工夫之后就不发送到服务器了)。简略名/值对模式的cookie只在以后会话期间存在,用户敞开浏览器就会失落。如果想让cookie的生命周期超过单个浏览对话,那就指定Expires/Max-Age,max-age优先级高于expires。Secure:设置之后,只在应用SSL平安连贯的状况下才会把cookie发送到服务器。例如,申请https://www.wrox.com会发送cookie,而申请http://www.wrox.com则不会。HttpOnly:设置了 HttpOnly 属性的 cookie 不能应用 JavaScript 经由 Document.cookie 属性、XMLHttpRequest 和 Request APIs 进行拜访,以防备跨站脚本攻打(XSS)。HTTP/1.1 200 OKContent-type: text/htmlSet-Cookie: name=value; domain=.wrox.com; path=/; secureOther-header: other-header-value这里创立的cookie对所有wrox.com的子域及该域中的所有页面无效(通过path=/指定)。不过,这个cookie只能在SSL连贯上发送,因为设置了secure标记。 要晓得,域、门路、过期工夫和secure标记用于通知浏览器什么状况下应该在申请中蕴含cookie。这些参数并不会随申请发送给服务器,理论发送的只有cookie的名/值对。 4.Javascript 中的cookie一般说来,cookie的生成形式次要有两种,一种是上文提到的在响应中通过Set-Cookie头部告知客户端;另外一种就是在JavaScript中能够通过document.cookie能够读写cookie,如下: //读取浏览器中的cookieconsole.log(document.cookie);//写入cookiedocument.cookie='myname=langlixingzhou;path=/;domain=.baidu.com';在JavaScript中解决cookie比拟麻烦,因为接口过于简略,只有BOM的document.cookie属性。在设置值时,能够通过document.cookie属性设置新的cookie字符串。这个字符串在被解析后会增加到原有cookie中。设置document.cookie不会笼罩之前存在的任何cookie,除非设置了已有的cookie。要为创立的cookie指定额定的信息,只有像Set-Cookie头部一样间接在前面追加雷同格局的字符串即可: document.cookie = encodeURIComponent("name") + "=" + encodeURIComponent("Nicholas") + "; domain=.wrox.com; path=/";// 应用encodeURIComponent()对名称和值进行编码5.cookie的缺点cookie 不够大每个cookie的大小为4KB(名字和值都蕴含在这4KB之内),对于简单的存储需要来说是不够用的。当 cookie 超过 4KB 时,它将面临被裁切的命运。这样看来,cookie 只能用来存取大量的信息。此外很多浏览器对一个站点的cookie个数也是有限度的(一般来说不超过300个cookie)。 ...

March 29, 2021 · 2 min · jiezi

关于前端:Chrome关闭安全策略-解决跨域

chrome版本号49之前的跨域设置间接在关上命令上加参数--disable-web-security 设置时敞开所有的chrome浏览器步骤:右键chrome快捷打开方式图标-->属性-->指标在指标门路的最初边,增加参数--disable-web-security,留神门路和参数之间有个空格 chrome版本号49之后的跨域设置须要在下面的根底上,多减少参数--user-data-dir

March 25, 2021 · 1 min · jiezi

关于cookies:记一次Chrome更新带来的登录Cookie问题

事件起因环境首先介绍下根本信息:公司的某个业务零碎是h.xxx.com,登录走的通过iframe嵌入的网页passport.xxx.com。 本地开发环境下,业务零碎只反对http协定,所以对应拜访地址为http://h.xxx.com,登录接口始终是https://passport.xxx.com。 这样就是一个跨协定的状况了。 问题某一天,有同学登录零碎后始终提醒“你未登录,请先登录B站”,而且并不是所有人有该问题。 通过一系列排查,发现惟一的区别只有Chrome浏览器版本不统一(应用局部其余浏览器也是没有问题的)。 结案从v88降级到v89后,Chrome浏览器内置的schemeful-same-site规定默认值改为启用,导致跨协定也被认定为跨站(cross-site),cookies无奈传递。 长期解决方案:地址栏关上chrome://flags/#schemeful-same-site,将选项设置为Disabled。 在Chrome 80版本,SameSite的默认值被改为Lax。Same-Site 的概念 eTLD+1局部统一就能够称之为same-site。 scheme和eTLD+1局部统一则被称为schemeful same-site 上面是一些schemeful same-site的案例: Origin AOrigin Bschemeful same-sitehttps://www.example.com:443https://www.evil.com:443cross-site: 域名不同 https://login.example.com:443schemeful same-site: 容许子域名不同 http://www.example.com:443cross-site: 协定不同 https://www.example.com:80schemeful same-site: 容许端口不同 https://www.example.com:443schemeful same-site: 齐全匹配 https://www.example.comschemeful same-site: 容许端口不同Schemeful Same-SiteSchemeful Same-Site 是 same-site 的进阶版,通过协定+域名两个维度来定义,如果想深刻理解下,你能够浏览这篇文章:Understanding 'same-site' and 'same-origin' 。 这意味着 http://website.example 和https://website.example 相互之间是跨站(cross-site)的。如果你的网站曾经全副应用HTTPS,那Schemeful Same-Site不会有任何影响,否则应该尽快降级到HTTPS。 如果你的我的项目同时应用HTTP和HTTPS,那就很有必要理解相干规定,接下来将介绍一些场景以及与之对应的cookie行为。 以前能够通过设置SameSite=None; Secure来容许跨协定的cookies传输,原作者倡议不要应用这个长期解决方案,应该尽快全站部署HTTPS,事实上也的确是这样的,就像前文的登录问题,你永远不晓得浏览器给你的下一个“惊喜”是什么。浏览器相干设置Chrome和Firefox上提供了schemeful-same-site的配置入口。 Chrome 86 开始,批改chrome://flags/#schemeful-same-site选项为Enabled即是启用。Firefox 79 开始,关上about:config批改 network.cookie.sameSite.schemeful选项为true。在以前的浏览器更新中,为了避免跨站申请伪造(CSRF)攻打,曾经将SameSite=Lax设置为默认项。 然而攻击者还是能通过不平安的HTTP协定篡改cookies,影响到也应用同样cookies的HTTPS页面。 schemeful-same-site也就应运而生。 常见的跨协定场景导航跳转之前两个跨协定同域名的页面跳转是容许携带设为SameSite=Strict的cookies。 当初不同协定被认定为跨站(cross-site),所以设为SameSite=Strict的cookies就被阻挡了。 HTTP → HTTPSHTTPS → HTTPSameSite=Strict⛔ Blocked⛔ BlockedSameSite=Lax✅ Allowed✅ AllowedSameSite=None;Secure✅ Allowed⛔ Blocked加载子资源支流浏览器都会阻止 active mixed content(主动型混合内容) ,如scripts、iframe。 Chrome和Firefox浏览器正在尝试降级或阻止passive mixed content(被动型混合内容)。子资源(subresources)包含图片,iframes 以及 XHR、Fetch申请 ...

March 25, 2021 · 2 min · jiezi

关于前端:Chrome浏览器地址栏配置二维码自动生成工具

关上Chrome浏览器新开一个窗口地址栏输出 chrome://flags/ 搜寻qr code 下拉框抉择Enable选项 重启浏览器即可 点击须要生成二维码的网页地址栏 呈现如下图标 点击小图标即可吧以后网址生成二维码

March 23, 2021 · 1 min · jiezi

关于前端:技术分享PPT整理三网页渲染流程

在我刚开始学习Web开发的时候,始终有个疑难——我写出的代码到底是在什么时候产生作用的呢?是不是每次我批改代码网页都随之变动了?当然,当初来看这必定是一个谬误的想法,通过一段时间的工作和学习后,代码到页面转换的门路在我的脑海里愈发清晰,尽管“输出URL到网页显示之间产生了什么?”是个陈词滥调的问题,但我还是想按本人的了解来阐明一遍。 浏览器架构首先从咱们最相熟的敌人开始说起,Web开发离不开浏览器,我在查资料的时候有开很多选项卡的习惯,每次关上工作管理器都能看到Chrome浏览器在内存占用方面一枝独秀,另外还能看到利用名称前面的括号里有个数字,如下图所示,但我关上的标签页是不到23的,那么剩下的过程是什么呢? 咱们来看一张经典的图,它描述了Chrome浏览器中四种过程的地位和作用: 浏览器过程 (Browser Process):负责浏览器的TAB的后退、后退、地址栏、书签栏的工作和解决浏览器的一些不可见的底层操作,比方网络申请和文件拜访。渲染过程 (Renderer Process):负责一个Tab内的显示相干的工作,也称渲染引擎。插件过程 (Plugin Process):负责管制网页应用到的插件GPU过程 (GPU Process):负责解决整个应用程序的GPU工作 渲染过程较为非凡,每个选项卡里都须要一个渲染过程,它也是网页渲染的外围,咱们在下一节具体阐明,对于这些过程,能够在浏览器自带的过程管理器中具体查看: 因为常常要做多浏览器兼容,常常同时关上几个浏览器,即便没有认真比照还是能够发现Chrome浏览器在内存占用方面算是绝对比拟高的,而Firefox则绝对要低很多,这是因为Firefox的Tab过程和IE的Tab过程都采纳了相似的策略:有多个Tab过程,但都不肯定是一个页面一个Tab过程,一个Tab过程可能会负责多个页面的渲染。而作为比照,Chrome是以一个页面一个渲染过程,加上站点隔离的策略来进行的。尽管内存占用的确比拟高,然而这种多过程架构也有独特的劣势: 更高的容错性。当今WEB利用中,HTML,JavaScript和CSS日益简单,这些跑在渲染引擎的代码,频繁的呈现BUG,而有些BUG会间接导致渲染引擎解体,多过程架构使得每一个渲染引擎运行在各自的过程中,相互之间不受影响,也就是说,当其中一个页面解体挂掉之后,其余页面还能够失常的运行不收影响。更高的安全性和沙盒性(sanboxing)。渲染引擎会经常性的在网络上遇到不可信、甚至是歹意的代码,它们会利用这些破绽在你的电脑上装置歹意的软件,针对这一问题,浏览器对不同过程限度了不同的权限,并为其提供沙盒运行环境,使其更平安更牢靠更高的响应速度。在单过程的架构中,各个工作相互竞争争夺CPU资源,使得浏览器响应速度变慢,而多过程架构正好躲避了这一毛病。 网页渲染大抵来说,输出URL后要通过五个步骤网页才会渲染实现: DNS 查问TCP 连贯HTTP 申请即响应服务器响应客户端渲染首先,如果输出的是域名,浏览器会先从hosts文件中查找有没有对应的设置,如果没有则拜访左近的DNS服务器进行DNS查问获取正确的IP地址,之后进行TCP连贯,通过三次握手建设连贯后开始解决HTTP申请,服务器端收到申请返回响应文档,拿到响应文档的浏览器开始应用渲染引擎进行页面渲染。 这里说到的渲染引擎就是咱们常常说到的浏览器内容,例如Webkit、Gecko这些。 渲染引擎浏览器内核是多线程,在内核管制下各线程相互配合以放弃同步,一个浏览器通常由以下常驻线程组成: GUI 渲染线程负责渲染浏览器界面,解析HTML,CSS,构建DOM树和RenderObject树,布局和绘制等。当界面须要重绘(Repaint)或因为某种操作引发回流(reflow)时,该线程就会执行GUI渲染线程与JS引擎线程是互斥的,当JS引擎执行时GUI线程会被挂起(相当于被解冻了),GUI更新会被保留在一个队列中等到JS引擎闲暇时立刻被执行。JavaScript引擎线程也称为JS内核,负责解决Javascript脚本程序。(例如V8引擎)JS引擎线程负责解析Javascript脚本,运行代码。JS引擎始终期待着工作队列中工作的到来,而后加以解决,一个Tab页(renderer过程)中无论什么时候都只有一个JS线程在运行JS程序同样留神,GUI渲染线程与JS引擎线程是互斥的,所以如果JS执行的工夫过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞。定时触发器线程传说中的setInterval与setTimeout所在线程浏览器定时计数器并不是由JavaScript引擎计数的,(因为JavaScript引擎是单线程的, 如果处于阻塞线程状态就会影响记计时的精确)因而通过独自线程来计时并触发定时(计时结束后,增加到事件队列中,期待JS引擎闲暇后执行)事件触发线程归属于浏览器而不是JS引擎,用来管制事件循环(能够了解,JS引擎本人都忙不过来,须要浏览器另开线程帮助)当JS引擎执行代码块如setTimeOut时(也可来自浏览器内核的其余线程,如鼠标点击、AJAX异步申请等),会将对应工作增加到事件线程中当对应的事件合乎触发条件被触发时,该线程会把事件增加到待处理队列的队尾,期待JS引擎的解决留神,因为JS的单线程关系,所以这些待处理队列中的事件都得排队期待JS引擎解决(当JS引擎闲暇时才会去执行)异步http申请线程在XMLHttpRequest在连贯后是通过浏览器新开一个线程申请将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件,将这个回调再放入事件队列中。再由JavaScript引擎执行。这五个线程各司其职,但咱们这里还是将眼光放到GUI渲染上: 渲染流程解决 HTML 标记并构建 DOM 树。解决 CSS 标记并构建 CSSOM 树将 DOM 与 CSSOM 合并成一个渲染树。依据渲染树来布局,以计算每个节点的几何信息。将各个节点绘制到屏幕上。 1. DOMTree的构建(Document Object Model) 第一步(解析):从网络或者磁盘下读取的HTML原始字节码,通过设置的charset编码,转换成字符 第二步(token化):通过词法分析器,将字符串解析成Token,Token中会标注出以后的Token是开始标签,还是完结标签,或者文本标签等。 第三步(生成Nodes并构建DOM树):浏览器会依据Tokens里记录的开始标签,完结标签,将Tokens之间互相串联起来(带有完结标签的Token不会生成Node)。 2. CSSOMTree的构建(CSS Object Model)当HTML代码遇见<link>标签时,浏览器会发送申请取得该标签中标记的CSS文件(应用内联CSS能够省略申请的步骤进步速度,但没有必要为了这点速度而失落了模块化与可维护性),style.css中的内容见下图: 浏览器取得内部CSS文件的数据后,就会像构建DOM树一样开始构建CSSOM树,这个过程没有什么特地的差异。 从图中能够看出,最开始body有一个款式规定是font-size:16px,之后,在body这个款式根底上每个子节点还会增加本人独自的款式规定,比方span又增加了一个款式规定color:red。正是因为款式这种相似于继承的个性,浏览器设定了一条规定:CSSOMTree须要等到齐全构建后才能够被应用,因为前面的属性可能会笼罩掉后面的设置。比方在下面的css代码根底上再增加一行代码p {font-size:12px},那么之前设置的16px将会被笼罩成12px。 看到这里,感觉如同少了什么?咱们的页面不会只蕴含HTML和CSS,JavaScript通常也在页面中占有很大的比重,并且JavaScript也是引发性能问题的重要因素,这里通过解答上面几个问题来阐明JavaScript在页面渲染中的状况。 问题:渲染过程中遇到JS文件怎么解决? 因为JavaScript是可操纵DOM的,如果在批改这些元素属性同时渲染界面(即JS线程和UI线程同时运行),那么渲染线程前后取得的元素数据就可能不统一了。 因而为了避免渲染呈现不可预期的后果,浏览器设置GUI渲染线程与JS引擎为互斥的关系,当JS引擎执行时GUI线程会被挂起, GUI更新则会被保留在一个队列中等到JS引擎线程闲暇时立刻被执行。 也就是说,在构建DOM时,HTML解析器若遇到了JavaScript,那么它会暂停构建DOM,将控制权移交给JavaScript引擎,等JavaScript引擎运行结束,浏览器再从中断的中央复原DOM构建。 问题:为什么有时在js中拜访DOM时浏览器会报错? ...

March 23, 2021 · 1 min · jiezi

关于chrome:前端面试每日-31-第705天

明天的知识点 (2021.03.21) —— 第705天 (我也要出题)[html] 在页面中能关上.doc或者.xlsx后缀的文件吗?如果能够应该怎么做?[css] 说说你对transition-timing-function属性的了解[js] js如何遵循凋谢关闭准则?[软技能] 为什么在chrome浏览器中关上多个标签页,其中一个解体了不会影响其它的标签页呢?《论语》,曾子曰:“吾日三省吾身”(我每天屡次检查本人)。前端面试每日3+1题,以面试题来驱动学习,每天提高一点!让致力成为一种习惯,让奋斗成为一种享受!置信 保持 的力量!!!欢送在 Issues 和敌人们一起探讨学习! 我的项目地址:前端面试每日3+1【举荐】欢送跟 jsliang 一起折腾前端,零碎整顿前端常识,目前正在折腾 LeetCode,打算买通算法与数据结构的任督二脉。GitHub 地址 微信公众号欢送大家前来探讨,如果感觉对你的学习有肯定的帮忙,欢送点个Star, 同时欢送微信扫码关注 前端剑解 公众号,并退出 “前端学习每日3+1” 微信群互相交换(点击公众号的菜单:交换)。 学习不打烊,充电加油只为遇到更好的本人,365天无节假日,每天早上5点纯手工公布面试题(死磕本人,愉悦大家)。心愿大家在这虚夸的前端圈里,放弃沉着,保持每天花20分钟来学习与思考。在这变幻无穷,类库层出不穷的前端,倡议大家不要等到找工作时,才狂刷题,提倡每日学习!(不忘初心,html、css、javascript才是基石!)欢送大家到Issues交换,激励PR,感激Star,大家有啥好的倡议能够加我微信一起交换探讨!心愿大家每日去学习与思考,这才达到来这里的目标!!!(不要为了谁而来,要为本人而来!)交换探讨欢送大家前来探讨,如果感觉对你的学习有肯定的帮忙,欢送点个[Star]

March 21, 2021 · 1 min · jiezi

关于angular:Angular-Lazy-load学习笔记

Lazy loading, also known as code splitting, lets you divide your JavaScript code into multiple chunks. The result is that you do not have to load all the JavaScript of the full application when a user accesses the first page. Instead, only the chunks that are required for the given page are loaded.懒加载能够容许咱们将TypeScript编译出的JavaScript代码拆分成若干个chunk, 这样,当应用程序加载时,咱们无需将整个利用所需的所有chunk都加载到浏览器中,而是能够实现按需加载的机制,即仅加载那些须要渲染的页面对应的chunk. 咱们在Angular我的项目里执行命令行ng build,即可查看打包进去的chunk名称和对应的大小,如下图所示。 默认状况下,咱们在Angular利用里编写的所有Component,会被ng build打包到一个main chunk里。比方我开发了一个MyCartComponent: 打包到main chunk后对应的JavaScript代码如下: 如何让一个Angular利用的Component反对lazy load,行将其和main chunk离开进行打包呢? 看个例子。 在AppRoutingModule里,配置路由信息时,不应用惯例的Component属性,而是采纳loadChildren,为某个path动静地指定要加载的Component名称: ...

March 20, 2021 · 2 min · jiezi

关于chrome:深入了解现代web浏览器二-导航

导航栏产生了什么?这是介绍Chrome外部工作博客系列的第2局部。在上一篇博客中,咱们学习了不同的过程和线程去解决浏览器的不同局部。在这篇文章,咱们深刻去理解为了展现一个网页每个过程和线程是如何通信的。 咱们看一下web浏览器的一个简略示例:当你在浏览器中输出一个url,浏览器从网络获取数据并且显示一个页面。在本文中,咱们将重点介绍用户申请站点和浏览器筹备渲染一个页面(也称之为导航)。 从浏览器过程开始正如咱们在第一局部中介绍的CPU、GPU和多过程架构,选项卡之外的所有内容都是浏览器过程解决的。浏览器过程具备线程,例如用于绘制按钮和输出局部的UI线程,用于解决网络堆栈和从网络获取数据的网络线程,用于管制拜访文件的存储线程。在地址栏中输出URL,你的输出将由浏览器过程的UI线程解决。 简略的导航步骤1:解决输出当一个用户开始在地址栏中输出内容,UI线程首先问“这是搜寻还是一个URL?”。在Chrome中,地址栏也是一个搜寻输出区域,因而UI线程须要解析并且决定将内容发送给搜索引擎,还是你申请的网站。 步骤2:开始导航当用户按下Enter键,UI线程会开始调用网络申请去获取站点内容。在选项卡的角上显示loading旋转,网络线程通过相应的协定,例如DNS查找,为申请建设TLS连贯。 此时,网络线程可能会收到服务器的重定向头比方http 301。在这种状况下,网络线程与UI线程开始通信,服务器申请重定向。而后,会启动另一个URL申请。 步骤3:读取响应一旦响应体开始回来,网络过程将在必要的时候查看流的前几个字节。响应的Content-Type头会阐明是哪种数据类型,然而可能会失落或者谬误,MIME Type嗅探会在这里实现。就像源码中形容的一样这是一个“辣手的业务”。你能够浏览正文去理解不同浏览器如何解决content-type/payload对。 MIME Type嗅探MDN解释:在缺失 MIME 类型或客户端认为文件设置了谬误的 MIME 类型时,浏览器可能会通过查看资源来进行MIME嗅探。每一个浏览器在不同的状况下会执行不同的操作。因为这个操作会有一些平安问题,有的 MIME 类型示意可执行内容而有些是不可执行内容。浏览器能够通过申请头 Content-Type 来设置 X-Content-Type-Options 以阻止MIME嗅探。如果响应是一个HTML文件,那么下一步须要将数据传递到渲染过程,然而如果是zip文件或者其余文件,则意味着这是一个下载申请,因而须要将数据传递到下载管理器。 也是在这里进行平安浏览查看。如果域名和响应数据与已知的歹意站点匹配,那么网络过程会弹出一个正告去显示一个正告页。此外,Cross Origin Read Blocking(CORB)触发是为了确保敏感站点数据不传递给渲染过程。 在谷歌的官网是这么解释的:Cross-Origin Read Blocking (CORB) is an algorithm that can identify and block dubious cross-origin resource loads in web browsers before they reach the web page. CORB reduces the risk of leaking sensitive data by keeping it further from cross-origin web pages. In most browsers, it keeps such data out of untrusted script execution contexts. In browsers with Site Isolation, it can keep such data out of untrusted renderer processes entirely, helping even against side channel attacks like Spectre.步骤4:查找渲染过程当所有的查看都实现,并且网络线程确认导航到申请的站点,网络线程就会告诉UI线程数据筹备好了。UI线程就会查找一个渲染过程负责渲染web页面。因为网络强求须要破费数百毫秒能力失去响应,因而有一个优化用来放慢此过程。当UI线程在第2步发送一个URL申请给网络线程的时候,它一句晓得了须要导航到的站点是哪个。UI线程被动地尝试查找,并且启动一个与网络申请并行的渲染过程。这样,如果所有合乎预期,当一个网络过程接管到数据的时候,渲染过程曾经处于筹备好的状态。如果导航重定向跨站点那么该筹备好的过程就无奈应用,在这种状况下,可能须要另外一个过程。 ...

March 16, 2021 · 1 min · jiezi

关于chrome:了不起的Chrome浏览器Chrome-89开启Web应用的物联网时代

3月初刚公布的Chrome 89,带来了哪些有意思的新个性呢? 背景十多年来,Web技术突飞猛进,这其中,Chrome功绩是最大的,能够说没有之一。对于这一点,我在之前的博客中曾经阐述过了: JavaScript深入浅出第5课:Chrome是如何胜利的?第三方cookie马上就不让用了,互联网广告还怎么玩?当初,Chrome曾经不只是一个简略的浏览器,而是一个决定Web技术倒退方向的平台型产品,它的位置也就仅次于Linux、iOS、Andirod和Windows吧。 重要的是,Chrome并没有停下翻新的脚步,始终在推动Web技术往前倒退。 始终以来,Chrome每隔 6 周公布一个新版本。最近,Chrome发表将会放慢这个公布流程,改为每 4 周公布一个新版本。 身处大前端这个畛域,理解Chrome的倒退能够帮忙咱们了解整个行业的发展趋势。 Chrome最值得关注的新个性有2个方向: 新的能力,新的API,比方Web NFC这种,能够用在理论的利用场景中,带来业务上的翻新;平安及隐衷方面的规定批改,比方禁用第三方Cookie,会影响到业务的稳定性;从这篇文章开始,我将以《了不起的Chrome浏览器》为题,对Chrome的每一个版本进行具体解读,分享一些本人兴许并不成熟的思考,欢送关注寒雁Talk公众号。 TL;TR为了防止占用过多公共资源,我先简略总结一下吧:) Chrome 89是哪天公布的?2021-03-02在哪能够查看Chrome的版本信息?Chrome Platform StatusChrome 89更新了多少个个性?30个,具体有哪些个性能够查看Chrome Platform StatusChrome 89最大的亮点是什么?、Web NFC、WebHID以及Web Serial API,这3个个性使得Web利用能够更加便捷地与硬件进行交互,JavaScript或成为物联网时代的最大赢家。我感兴趣的新个性顺次有哪些? Top-level awaitWeb NFCWebHIDWeb Serial API performance.measureUserAgentSpecificMemory()你感兴趣的新个性顺次有哪些?这个我就不晓得了啊,欢送留言评论!这里,必须点赞Chrome Platform Status这个站点,它把Chrome每一个版本的每一个个性都整顿得十分分明。而我做的事件,无非是做个勤奋的搬运工就好了~ 具体解读30个新个性我无奈一一介绍,那我就挑5个还比拟有意思的个性来聊聊吧,对其余个性感兴趣的话,能够看看Chrome Platform Status。 Top-level await作为一个JavaScript程序员,Async/Await是我最喜爱的个性之一,把我从Promise.then的天堂中解脱进去。爱屋及乌,Top-level await也很妙啊。 上面这个html,在Chrome 88上会报错:"Uncaught SyntaxError: Unexpected reserved word",在Chrome 89上则能够正确执行。这是因为Chrome 89的V8引擎降级到了V8.9,反对了Top-level await。 <!DOCTYPE html><head> <title>Top-level await</title></head><body> <script type="module"> await Promise.resolve(alert('hello, world!')); </script></body>以前,await只能在async函数中应用,当初毋庸async函数也能够应用了,能够利用在数据库连贯初始化等场景,更加不便: const connection = await dbConnector();值得注意的是,Top-level await只能在ES Module中应用。并且,应用Top-level await的话,会对ES Module的执行程序造成影响,阻塞应用了Top-level await的Module及其父节点(parent module)的执行。 ...

March 15, 2021 · 2 min · jiezi

关于chrome:vue实现滚动超过首屏高度位置点击小盒子回到顶部效果火狐IE均有效

思路剖析回到顶部成果,思路其实很简略。就是初始有一个盒子,固定定位在浏览器网页的右下角,一开始要暗藏起来。当滚动超过首屏高度的地位时,才让其呈现。给这个小盒子绑定一个点击事件,在点击事件的回调中,应用定时器去让滚动条的高度递加,从而实现回到顶部成果。当然也要绑定滚动事件,监听滚动的高度,即监听滚动条的纵坐标的地位。因为须要拿滚动条滚动的高度和首屏的高度做比拟。话不所说,先看一下最终效果图: 请依照正文来哦代码附上<template> <div id="app"> <p v-for="(item, index) in arr" :key="index">回到顶部</p> <div class="back" v-show="showGoTop" @click="goToTop">back</div> </div></template><script>export default { data() { return { arr: [], showGoTop: false, }; }, mounted() { for (let index = 0; index < 54; index++) { this.arr.push(index); } // 第一步,绑定一个滚动事件,当滚动的间隔达到浏览器窗口的外部高度的时候(大略一个屏幕的高度吧) // 就让回到顶部的小盒子显示进去 window.addEventListener("scroll", this.handleScroll,true); // 这里加上true是为了保障浏览器滚动的及时性 }, methods: { // 滚动事件的回调函数 handleScroll() { let scrolltop = document.documentElement.scrollTop; // 获取以后页面的滚动条纵坐标地位 console.log("看看滚动了多高的间隔",scrolltop); if(scrolltop > window.innerHeight){ // 浏览器窗口的外部高度 window.innerHeight this.showGoTop = true // 超过就显示进去 }else{ this.showGoTop = false // 不超过还藏起来 } }, // 第二步,当用户点击回到顶部小盒子的时候,依然获取所在的页面的滚动条纵坐标地位, // 应用定时器让页面滚动条的坐标地位递加,这样就能实现平滑过渡的成果 goToTop() { let scrolltop = document.documentElement.scrollTop; // 获取以后页面的滚动条纵坐标地位 // 定时器平滑滚动 const time = setInterval(() => { document.documentElement.scrollTop = scrolltop -= 40; if (scrolltop <= 0) { // 定时器要及时革除掉,要不然始终执行很恐怖的 clearInterval(time); } }, 10); }, },};</script><style lang="less" scoped>p { margin-bottom: 30px;}.back { width: 60px; height: 60px; line-height: 60px; text-align: center; background-color: #abf; position: fixed; right: 100px; bottom: 100px; cursor: pointer;}</style>总结好忘性不如烂笔头,记录一下 ...

March 11, 2021 · 1 min · jiezi

关于chrome:chroem-89-打开新标签-sessionStorage-失效

前几天工作中遇到一个奇怪的问题,记录一下。 我的项目信息:Vue + Element UI 做的后盾管理系统。 问题应用 <a> 链接关上新标签时,页面跳转到了登录页。 起因查看后发现新标签的 sessionStorage 是空的!因为我把 token 保留在了 sessionStorage 外面,所以当 sessionStorage 为空时间接跳转了登录页。 然而,为啥是空的??之前还好好的呀,并且,共事电脑关上我的项目是没问题的! 兜兜转转一下午,把问题锁定在了 chrome 的版本上,而后就搜寻到了上面这一问题: https://stackoverflow.com/questions/66473527 原来 chrome 89 版本批改了关上新标签时 sessionStorage 的解决逻辑,这其实波及到 <a> 标签的 rel 属性,咱们举例来说明一下批改前后的区别: 比方说咱们从 A 标签通过 a 链接关上了一个新的 B 标签, 之前浏览器的解决逻辑:当 a 标签的 target="_blank" 时,浏览器默认会增加 rel="opener" 属性,这时 B 标签的上下文(蕴含 sessionStorage)是从 A 标签复制而来的,并且能够通过 window.opener来拜访 A 标签的 window 对象。没错,当 B 标签不是咱们本人的网站时,这时一个极其危险的行为! 当初浏览器的解决逻辑:当 a 标签的 target="_blank" 时,浏览器默认会增加 rel="noopener" 属性,这时 B 标签的上下文是一个全新的,空白的上下文,并且 B 标签不能够通过 window.opener 来拜访 A 标签的 window 对象。很平安! ...

March 11, 2021 · 1 min · jiezi

关于chrome:vue-css-deep穿透深度查询样式在chrome89-edge最新版本中无效问题

利用vue开发我的项目过程中,控制台始终有正告⚠️ 揭示如下图,然而始终没有解决,因为大略上网查了一下据说只有在vue-cli3以上版本不能够,思考到我的项目应用的是vue2.5.17,所以就懒得弄了,直到最近chrome与edge浏览器更新版本后,问题呈现了(看来新的框架技术和浏览器都摈弃了这个货色),才想起来解决这个问题;[Deprecation] /deep/ combinator is no longer supported in CSS dynamic profile. It is now effectively no-op, acting as if it were a descendant combinator. /deep/ combinator will be removed, and will be invalid at M65. You should remove it. See https://www.chromestatus.com/... for more details. 关上给出的链接,过滤查问发现,有对于/deep/破除后的解决办法: 地址:https://www.chromestatus.com/... 大略了解应该是/deep/基本上有效了,间接替换成“”空格,或者>>>代替解决; 于是,在我的项目中全局替换/deep/为空格,然而局部页面会有错乱问题,于是将替换为空格后,依然有效的款式局部,增加>>>,竟然能够了,然而对于Sass Less之类的预处理器是无奈正确解析 >>>的,所以要保障款式是css文件; 还有一点要强调,>>>在html单页面下貌似有效,在vue我的项目中无效; 我的项目问题根本解决后,做一下汇总的状况下,上网查看对于款式穿透,发现除了>>>、/deep/外,还有一个::v-deep,写法如下:`<style lang="scss" scoped> /用法1/ .a{ ::v-deep .b { } } /用法2/ .a ::v-deep .b {}</style>`以上,是我的项目上值得记录的问题解决办法;

March 10, 2021 · 1 min · jiezi

关于chrome:vscode使用chrome调试报错

问题vscode应用chrome调试报错"无法访问您的文件"或者"localhost 回绝了咱们的连贯申请"。解决ctrl+p 搜寻launch.json文件 改为: { "version": "0.2.0", "configurations": [ { "name": "应用本机 Chrome 调试", "type": "chrome", "request": "launch", "file": "${file}", // "runtimeExecutable": "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe", // 改成您的 Chrome 装置门路 "sourceMaps": true, "webRoot": "${workspaceRoot}", "userDataDir":"${tmpdir}", "port":9222 } ]}vscode应用chrome调试报错

March 9, 2021 · 1 min · jiezi

关于chrome:AI在出行场景的应用实践路线规划ETA动态事件挖掘…

简介: 本文是#春招专栏#系列的第1篇,依据高德机器学习研发部负责人damon在AT技术讲坛所分享的《AI在出行畛域的利用实际》的内容整顿而成。 前言:又到春招季!作为国民级出行服务平台,高德业务疾速倒退,大量校招/社招名额凋谢,欢送大家投递简历,详情见文末。为帮忙大家更理解高德技术,咱们策动了#春招专栏#的系列文章,组织各业务团队的高年级同学以科普+利用实际为次要内容为大家做相干介绍。AT技术讲坛(Amap Technology Tribune)是高德发动的一档技术交流活动,每期围绕一个主题,咱们会邀请阿里团体内外的专家以演讲、QA、凋谢探讨的形式,与大家做技术交换。 damon依据用户在出行前,出行中和出行后如何应用导航服务,别离选取了几个典型的业务场景来介绍AI算法在其中的利用,最初对将来做了一些瞻望。 以某位同学周末和敌人相约去“木屋烧烤”店撸串为例,假如这位同学抉择驾车返回目的地,咱们来看下AI算法是如何在导航过程中起到作用的。 出行前,先做路线布局,ETA(预估达到工夫),不要早退;出行中,最怕的就是遇到突发动静事件而影响到出行工夫;出行后(到目的地),餐馆是否还在失常营业,也须要通过技术开掘,帮忙用户提前躲避白跑一趟的危险。 上面别离介绍。 出行前-路线布局 路线布局,和网页搜寻,商品搜寻的举荐算法很类似,为用户举荐一条合乎集体爱好的优质路线。举荐的路线要合乎以下几个条件: 能走:此路能通,依照路线能够达到起点。好走:路线品质在以后地点工夫下确保优质。千人千面:不同用户在保障路线优质的前提下,个性化调整更合乎用户偏好。同时,在不对用户产生误导的前提下,提供更多的比照参考给用户来抉择: 优质:相比首路线/主路线,有肯定的、用户可感触到的劣势。多样:相比首路线/主路线,尽可能有本人的专长。路线布局算法的特点 从用户产生出行需要,到需要失去满足。在用户搜寻的时候,上传的Query除了有起起点和导航策略,也会像其余搜寻一样,有隐含的需要,比方个性化和场景化。在导航业务外面,个性化能够拆分成熟路和偏好两个维度,熟路比拟容易了解,偏好是指用户对工夫、间隔、红绿灯、免费等不同维度上的偏好。 那么,对应的解决方案,咱们引入用户ID,存储记忆了用户的起起点对应的熟路信息。对用户的偏好,相似DIN的网络结构,对用户历史导航序列进行建模,获取用户偏好信息。 在用户提交搜寻需要之后,对导航引擎来说,也分为召回,排序和过滤几局部。 对于导航的召回,对性能要求比拟高,所以目前召回的后果较少。对排序来说,同样是多指标,而且多指标之间要进行均衡的业务。类比到电商举荐畛域,不仅心愿用户更多地对商品进行点击浏览,还心愿用户在看完商品介绍之后进行购买,进步GMV。 对于地图出行,不仅心愿用户更多的应用导航且依照举荐的路线走,还心愿实走工夫要尽可能短,用户反馈尽量好。 而且,和其余畛域相似,多个指标之间会存在抵触,比方电商CTR和GMV。在导航畛域,让用户尽可能的走关闭路线,没有进口,那必定实走覆盖率就回升了,然而这样布局的路线会绕远,工夫和间隔都变差。 多指标的均衡,如何在“帕累托最优”的状况下,进行多个指标之间的取舍、均衡,是大家始终在摸索的问题,咱们目前采纳的是带束缚的最优化问题来进行建模,就是保障其余指标不变差的状况下,把某个指标最优化。 最初,用户拿到导航引擎返回的路线后果,特点是信息少,用户只能看到整条路线的总工夫、总间隔和免费等统计信息,对于这条路好不好走,能不能走很难晓得。 而且,大部分用户是在生疏场景下用导航,对导航依赖很重,很难决策走哪条路更好,这就导致排序在首条的计划选择率很高,达到90%以上,这个偏置是很重大的,在训练实走覆盖率的时候,咱们设计了偏置网络,来排汇用户这种偏向。 导航还有一个特点,一旦出错,对用户挫伤特地大,比方遇到小路,用户的车可能会呈现刮蹭;遇到封路,用户可能就得绕路,付出相当的工夫和金钱老本。这往往会比信息搜寻给用户带来的影响和挫伤更大。所以,咱们在过滤阶段,对Badcase的过滤也是严格作为束缚要求的。 路线布局召回算法 路线布局算法,经典的是教科书上的Dijkstra算法,存在的问题就是性能比拟差,线上理论利用都做了优化,这里就不开展介绍了。 当起起点间隔超过500公里,性能根本就不可承受了,尽管有启发式A star算法,然而A star算法有可能丢最优解,并不是完满解决性能问题的办法。 解决性能问题的思路,一个是分布式,一个是Cache,而最短路线搜寻并不像网页搜寻,分布式并不能很好的解决性能问题,所以目前工业界理论应用的算法都是基于Cache的办法。 Cache的办法就是提前把一些起起点对之间的最短路线计算好(Shortcuts),在用户申请过去的时候,利用好这些Shortcuts,达到放慢求路的目标(简略举例子,比方从北京到广州,如果提前计算好了从北京到济南,济南到南京,南京到广州的最短门路,那就能够在计算北京到广州的时候,利用这些提前计算好的最短路线)。 其中最为经典的一个算法就是CH算法(Contraction Hierarchies),在预处理阶段,对所有节点进行了重要性排序,逐步把不重要的点去掉,而后减少Shortcuts;Query查问阶段,从终点和起点别离开始双向求路,只找重要性高的点,来达到减速的目标。 既然是Cache,就会面临一个更新的问题,比方原始路网的路况变动了,或者原始路网某条路封路了,那么提前缓存好的Shortcuts也须要更新。 这个时候CH的算法,因为Shortcuts结构设计不够法则,更新就很慢,无奈响应实时路况的变动。于是,路线布局算法推动到了下一代,CBR算法(Cell based Routing),这个算法通过分而治之的思维,在预处理阶段,把全国路网切分成n个子图,切分的要求是子图之间连贯的边(边界边)尽可能的少。 在每个子图内,再持续往下切分,进而造成金字塔构造,预处理阶段就是把边界边之间的最短门路都提前算好,Cache下来求路的时候,就能够利用这些Shortcuts了。 CBR的长处是,在预处理阶段,路网的切分是分层的,每一层都足够小,在更新这一层的Shortcuts的时候,能够把数据都放到CPU的L1 Cache里去,所以计算速度特地快。 总结一下CBR和CH的区别: Query查问性能,CH更快,CH是0.1ms级别,CBR是1-2ms级别。Shortcuts更新性能,CH全国路网更新最快能做到10分钟,而CBR能做到15秒更新全国,能够满足实时路况变动和路网实时更新的需要。CH的Shortcuts不法则,导致不同策略之间(规避拥挤,高速优先等)不能很好的复用Shortscuts的起起点构造,所以不同策略须要独自重建Shortcuts,内存占用十分大。 这是咱们排序的网络结构,右边是用户偏置网络,把路线排序的程序,以及疏导路线之间的类似度信息输出进去,冀望尽可能打消掉偏置带来的影响。两头输出的用户历史统计信息和用户导航序列信息,用来提取用户的个性化偏好。优化的次要指标是实走覆盖率。 新一代的路线布局算法,要求提供随工夫推演的能力。比方8:00从终点登程,前面要走 1 2 3 ..n条路达到目的地,假如8:10走到第2条路线,8:20走到第3条路线,那么咱们在8:00计算Shortcuts的时候,就不能只用到8:00的路况,须要把后续进入某个路线的时刻思考进来,用那个时刻的路况来计算,这就是TDR求路算法,目前是高德独创的,能真正实现规避将来的拥挤,并利用将来的畅通来布局门路。 出行前-ETA(预估达到工夫) 下面三幅图,选取的是北京西单金融街左近的区域,展现了在三个相邻工夫点上的交通状况。其中绿色、黄色、红色代表交通路况不同的状态。 假如当初是18点整,路况预测的指标就是预估将来时刻的交通状况,须要依赖每条路线的历史信息,以及周边街坊的路线拥挤信息,对时空两个维度进行建模。 对工夫序列的建模,用RNN,LSTM等SEQ2SEQ的序列,也有采纳CNN,TCN等。对空间信息的建模,目前支流的办法是用GRAPH. 只管模型在一直降级,越来越简单,然而对于突发事件导致的拥挤,依据历史统计信息,很难预测精准,比方去年9月份在上海世博园区举办外滩大会,世博园平时很少有人去,历史路况都是畅通,而在散会期间,车很多导致很堵。 这个时候靠历史信息是很难预测精确,咱们须要一个能代表将来的信号,能力预测,这就是路线布局的信息,如果想去世博园的人很多,那么布局的量就会很多,咱们依据布局的量,就能晓得将来有很多人想要去世博园,就会导致世博园拥挤。 所以,咱们把布局的量,通过一个流量往工夫域的转换,引入到路况预测模型,成果获得显著晋升,尤其是在突发拥挤的时候,高德的这个研究成果被KDD2020收录,并且曾经在业务场景中失去了利用,有趣味的同学能够具体查看咱们的论文。 行中-用文本数据挖掘动静交通事件 持续向餐馆后退,导航途中,最怕遇到拥挤,封路等事件,所以高德会想尽一切办法开掘这些动静事件,帮忙用户躲避开。当初高德用到了多个维度的数据源,其中的行业和互联网情报都是文本数据,要用到NLP的技术来开掘。 介绍一下怎么用AI算法来开掘动静事件。 上面一段文本就是典型的来自于网络媒体的信息: G0612(西和)高速南绕城路段西山隧道ZK33+844(兰州方向)应急车道停一辆故障大客车临时关闭,行车道和超车道失常通行,请车辆留神避让、减速慢行。 这段信息是非结构化的,须要咱们做预处理,因素提取,再进行事件的组织,组织成架构化的信息,能力自动化的利用。 很天然的,针对因素提取,咱们用BERT模型建模,然而BERT模型太简单,性能比拟差,线上理论利用带来很大的挑战。 咱们采取了常识蒸馏的办法,训练一个简略的Student的网络,来解决性能问题。常识蒸馏最次要的是如何捕获潜在语义信息。高德在业界率先提出了用比照学习框架进行常识蒸馏,同时,在计算样本之间间隔的时候,提出COS-间隔代替欧氏间隔的办法,可能让模型无效的学习到潜在语义表白信息。 对于Student表白的特征向量与Teacher特征向量间隔凑近,而要远离负例。应用余弦间隔,比方欧式间隔,可能更好适应Teacher网络和Student网络,输入的特征向量长度散布不统一的问题,这个工作成绩发表在了AAAI2021上。 ...

March 8, 2021 · 1 min · jiezi

关于chrome:这可能是大型复杂项目下数据流的最佳实践

简介: 理论我的项目中积淀的数据流最佳实际。 数据流是前端始终以来都存在的一个问题,咱们我的项目积淀了一套最佳实际,如有问题,欢送探讨在旧的 Done 我的项目中,代码复杂度高,曾经到了“牵一发而动全身”,技术债极高的状况。因为旧代码“盘根错节”,导致实现一个简略的性能,都须要比失常工夫多2~3倍的工作估时。就像上面这张图的状况一样。 咱们仔细分析下现有的业务,会得出上面的业务个性: 强畛域 (比方:我的项目/文件/团队/用户畛域,在很多组件都会同时调用某个畛域下的办法,静音/点赞/转移我的项目……)单页面多且简单,组件过多,多层嵌套组件间通信多。业务曾经实现了从 0~1 , 目前正处于从 1~n 的阶段,在这个阶段,会大量基于用户倡议而做出产品交互的调整以打磨精品。需要数量增长,前端变动大,前端人力瓶颈大。基于下面的业务个性,咱们再剖析目前我的项目中的问题: 模板代码过多,影响开发效率和可维护性数据流螺旋呈网状调用(强耦合),代码复杂度急剧回升,牵一发而动全身数据全局化原始数据与展现数据转换UI 与 数据逻辑耦合,复用低依据下面的特点和问题,咱们有以下的诉求: 简略高效回绝模版代码升高代码复杂度(升高联动影响)晋升复用性极大水平的复用 UI / 逻辑层复用 数据转换基于下面的问题和剖析,上面将一步步推导新的架构图 & 技术选型。 问题剖析一、 UI 与 数据逻辑耦合复用度低 & 原始数据与展现数据转换 原先的整体架构如下:Store 与 视图层混合在一起, 一起解决用户行为和业务逻辑,耦合度高,复用率低。 架构演进: 改良点:独立的 Store 层, 封装应用程序与业务逻辑相干的数据以及对数据的解决办法, 在此处独立写逻辑,反对多处组件复用一个逻辑,与视图层独立, 一个逻辑能够复用于多个组件。 家喻户晓,分层是为理解耦。假如 Store 层产生了扭转,那么在视图层不须要变动的,只须要批改 Store 层即可,这样改变的中央就少了,也晋升了开发效率&可维护性。 然而,咱们还遇到一些场景,当后端接口产生字段变动,要改变的中央切实太多太多。同一个接口,在不同中央展现,因为多人保护,他会通过屡次数据转换,最终映射到前端界面。因而,咱们再多一个API防腐层,专门解决前端界面和后盾界面的数据转换,这样,一旦数据结构发生变化,咱们也只须要在 API 层批改即可,毋庸关注到多个界面组件中。 改良点:独立 API 层, 连接后端服务与前端服务, 若后盾接口发生变化,可在此处进行对立批改,无需多处代码进行批改,不便在该层进行数据测验, 预防后盾返回谬误的字段等等。 通过下面这样的分层,下面2个问题就迎刃而解了。 二、数据流网状调用 咱们对 Store 和 视图进行了分层,然而随着我的项目的迭代,又呈现了上面这种状况,数据流呈网状调用。 举一个例子:对我的项目设置静音 在旧的代码中,工作站会调用到团队中的数据,也会批改到团队中的数据,甚至接口回调后,他还会对各个中央波及到静音界面的相干数据都进行批改。 这会带来一个问题,因为是全局共用的 Redux ,咱们在 A 中央调用这个办法,这里会更新 B 界面(B 中央并没有呈现在用户的界面上),也就是说,批改 A 中央的 action ,还须要同时关注 B,C,D…… 这些中央(实际上,咱们并不需要关注其余的中央) ...

March 8, 2021 · 2 min · jiezi

关于chrome:前端面试每日-31-第692天

明天的知识点 (2021.03.08) —— 第692天 (我也要出题)[html] 画一个ipad的页面布局[css] 应用css使得一个元素一闪一闪的[js] 写一个办法判断给定的数据是否为空对象[软技能] 如何率领团队做代码走读?如果有5万行的代码,要如何走读?用哪些方法论?《论语》,曾子曰:“吾日三省吾身”(我每天屡次检查本人)。前端面试每日3+1题,以面试题来驱动学习,每天提高一点!让致力成为一种习惯,让奋斗成为一种享受!置信 保持 的力量!!!欢送在 Issues 和敌人们一起探讨学习! 我的项目地址:前端面试每日3+1【举荐】欢送跟 jsliang 一起折腾前端,零碎整顿前端常识,目前正在折腾 LeetCode,打算买通算法与数据结构的任督二脉。GitHub 地址 微信公众号欢送大家前来探讨,如果感觉对你的学习有肯定的帮忙,欢送点个Star, 同时欢送微信扫码关注 前端剑解 公众号,并退出 “前端学习每日3+1” 微信群互相交换(点击公众号的菜单:交换)。 学习不打烊,充电加油只为遇到更好的本人,365天无节假日,每天早上5点纯手工公布面试题(死磕本人,愉悦大家)。心愿大家在这虚夸的前端圈里,放弃沉着,保持每天花20分钟来学习与思考。在这变幻无穷,类库层出不穷的前端,倡议大家不要等到找工作时,才狂刷题,提倡每日学习!(不忘初心,html、css、javascript才是基石!)欢送大家到Issues交换,激励PR,感激Star,大家有啥好的倡议能够加我微信一起交换探讨!心愿大家每日去学习与思考,这才达到来这里的目标!!!(不要为了谁而来,要为本人而来!)交换探讨欢送大家前来探讨,如果感觉对你的学习有肯定的帮忙,欢送点个[Star]

March 8, 2021 · 1 min · jiezi

关于chrome:Golangchromedpgoquery-简单爬取动态数据

[TOC] Golang+chromedp+goquery 简略爬取动态数据兵长: 胖sir,最近一段时间正在应用golang来进行开发我的项目,缓缓的对golang有了一些理解,忽然有一天,我想用golang来实现爬取网站上的数据,例如天气预报,每日一句等等,发现这些网站的数据都是javascript动静生成,苦恼呀,不晓得如何能力把网站上的动态数据获取下来,为我所用呀,例如我抓取到动态数据之后发邮件给我哟 胖sir撩撩了本人的长发,温和的对兵长说,小伙子,golang做利用开发效率很快的,当然爬取网站上的数据也是不在话下的哟,动静的也有动静的办法,来我给你娓娓道来 Golang的装置此步骤次要是为了关照没有在linux上装置过golang的童鞋们,若本人做过装置过golang的童鞋能够间接跳过golang简略装置步骤 下载golang软件【国内网站】https://studygolang.com/dl go语言中文网下载 go最新的安装包,依据不同的零碎,能够抉择 windows,linux,mac【能够上外网的话】拜访go语言英文网站 https://docs.studygolang.com/doc/install解压golangtar -C /usr/local -xzf go1.16.linux-amd64.tar.gz配置golang将go的二进制目录增加到PATH环境变量 vim /etc/profileexport GOROOT=/usr/local/goexport PATH=$PATH:$GOROOT/bin从新导入配置source /etc/profilechromedp框架的应用chromedp框架是github开源的,童鞋们能够释怀食用,若是有想法,能够在github上为此添砖加瓦,为开源做出本人的一份奉献 能够通过如下命令来进行下载 github.com/chromedp/chromedp理论的代码编写兵长,你想爬取每日一句的网站,我给你找一个例子,如爬取这个网站http://news.iciba.com/,咱们将网站上每天都会更新的一句话爬取出来 开始编码//获取网站上爬取的数据func GetHttpHtmlContent(url string, selector string, sel interface{}) (string, error) { options := []chromedp.ExecAllocatorOption{ chromedp.Flag("headless", true), // debug应用 chromedp.Flag("blink-settings", "imagesEnabled=false"), chromedp.UserAgent(`Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36`), } //初始化参数,先传一个空的数据 options = append(chromedp.DefaultExecAllocatorOptions[:], options...) c, _ := chromedp.NewExecAllocator(context.Background(), options...) // create context chromeCtx, cancel := chromedp.NewContext(c, chromedp.WithLogf(log.Printf)) // 执行一个空task, 用提前创立Chrome实例 chromedp.Run(chromeCtx, make([]chromedp.Action, 0, 1)...) //创立一个上下文,超时工夫为40s timeoutCtx, cancel := context.WithTimeout(chromeCtx, 40*time.Second) defer cancel() var htmlContent string err := chromedp.Run(timeoutCtx, chromedp.Navigate(url), chromedp.WaitVisible(selector), chromedp.OuterHTML(sel, &htmlContent, chromedp.ByJSPath), ) if err != nil { logger.Info("Run err : %v\n", err) return "", err } //log.Println(htmlContent) return htmlContent, nil}GetHttpHtmlContent做为一个爬取网站动态数据的接口,次要性能是爬取js生成的动态数据(当然静态数据更是不在话下)第一个参数 url即为咱们须要传入的要爬取的网站地址,页面如上第二个参数 selector即为咱们爬取的数据对应的选html择器, 通过谷歌浏览器进入网站,按F12 -> 点击左上角的鼠标 -> 再点击咱们须要爬取的数据 -> 就能够看到理论的html源码(目前看到的是通过javascript动静生成数据后的) ...

March 5, 2021 · 2 min · jiezi

关于chrome:缓存机制思维导图

jxjweb.top

March 5, 2021 · 1 min · jiezi

关于chrome:基于webkit的浏览器修改滚动条的样式如谷歌浏览器Safari浏览器Opera浏览器等

问题形容谷歌浏览器自带的滚动条的款式,不太好看。所以有时候可能要批改一下其款式。本文以vue的我的项目为例,针对于应用webkit内核的浏览器,其对应浏览器滚动条的款式管制都无效。 浏览器内核简介浏览器的内核引擎,基本上是三分天下: WebKit内核: Google Chrome、Safari、傲游3、猎豹浏览器、百度浏览器、opera浏览器等、都是基于Webkit开发的(edge浏览器也反对上面的css语法哦)Gecko内核: Firefox 是基于Gecko开发Trident内核: IE是基于Trident开发的代码代码图示 代码附上<!DOCTYPE html><html lang="en"><head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <link rel="icon" href="<%= BASE_URL %>favicon.ico"> <title> <%= htmlWebpackPlugin.options.title %> </title> <style> /* 仅实用于webkit的浏览器 */ /* 定义滚动条和滚动条轨道的宽度 */ ::-webkit-scrollbar { width: 15px; /* height: 100px; 这里就不必定义滚动条的高度了 因为高度的话,是依据内容自适应的 */ } /*定义滚动条 内暗影+圆角*/ ::-webkit-scrollbar-thumb { border-radius: 10px; -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, .3); background-color: pink; } /*定义滚动条滑动轨道 内暗影+圆角*/ ::-webkit-scrollbar-track { border-radius: 4px; background-color: #bfa; } /* 鼠标放上去成果 */ ::-webkit-scrollbar-thumb:hover { background: #baf; } </style></head><body> <noscript> <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong> </noscript> <div id="app"></div> <!-- built files will be auto injected --></body></html>效果图附上同理,如果要批改某个div的款式,只须要在类名前面加上上述的webkit伪元素即可,比方咱们批改一个类名为box的div的滚动条款式 ...

March 5, 2021 · 1 min · jiezi

关于chrome:谷歌浏览器更新速度大提升本月将用上Chrome-100

谷歌明天发表,一般版的Chrome浏览器将从2021年第三季度的Chrome 94开始,更新速度进步至每周围公布一次。此前谷歌始终每六周更新一次,偶然有较小的补丁推出。 Google Chrome Operations技术打算经理Alex Mineer在博客中示意,之所以决定缩短公布周期,是因为看到了针对Chrome的测试和公布流程的改良 ,能够反对更疾速的更新。值得注意的是,Mozilla去年也把Firefox的更新速度进步至每周围更新一次。 谷歌同时还发表,它将升高20个市场中产品最低价格的限度,使Android开发人员能够将其产品的价格设置在10-30美分之间,从而能够吸引更多的客户。 谷歌在博客中说:“这些超低的价格点(或称“亚美元”价格)使开发商者能够通过调整价格以更好地反映当地的购买力和需要来吸引新的潜在买家。 承受这些对付费应用程序,应用程序内产品和订阅的最低价格限度进行更改的市场有孟加拉国,玻利维亚,保加利亚,哥斯达黎加,克罗地亚,捷克共和国,丹麦,匈牙利,约旦,哈萨克斯坦,黎巴嫩,缅甸,巴基斯坦,巴拉圭,罗马尼亚,塞尔维亚,斯里兰卡,坦桑尼亚,泰国和越南。 谷歌也抵赖,并不是每个人都想这么快地更新,更快的更新周期意味着可能会迫使特定用户更频繁地适应新的更改,比方在学校和企业部署Chromebook的管理员,这在某些状况下可能很麻烦。为了解决这个问题,Google还提供了一个新的扩大稳定版,这个版本将更新周期定位8周,这样企业管理员和Chromium嵌入程序就能够应用扩大稳固更新周期。 不过对于大部分喜爱新性能的用户这感觉是个好消息,不出意外依照这种更快的速度,咱们将在2022年3月29日之前应用上Chrome 100稳定版。 内容起源:https://blog.chromium.org/2021/03/speeding-up-release-cycle.html

March 5, 2021 · 1 min · jiezi

关于chrome:ACK正式支持对基于Alibaba-Cloud-Linux操作系统的集群进行等保加固

简介: 咱们对基于Alibaba Cloud linux操作系统的ACK集群进行等保加固,意味着阿里云在云产品开发和交付的过程中将平安作为重要组成部分,将合规融入到产品的“血液”中,把平安植入产品的“骨髓”里,可能帮忙有等保诉求的客户更加疾速便捷的上云。前言依据国家信息安全部公布的《GB/T22239-2019信息安全技术网络安全等级爱护根本要求》,其中对操作系统提出了一些等级爱护的要求。同时,越来越多的企业、行业开始全面拥抱云原生,并充分利用云原生基础设施。云原生技术曾经无处不在, 作为云原生服务的提供者,阿里云将会继续、高速倒退云原生技术。而平安是云原生不可或缺的重要组成部分。Alibaba Cloud Linux 2 作为阿里云官网操作系统镜像和ACK的首选默认镜像,为ACK客户提供了等保加固的计划,来满足客户对于阿里云更加简略、快捷、稳固、平安的应用的需要。当用户创立ACK集群时,如果抉择Alibaba Cloud Linux 2, 就能够抉择启动配置等保加固,使集群在创立时主动执行对应的等保加固项,间接满足国家信息安全部公布的《GB/T22239-2019信息安全技术网络安全等级爱护根本要求》中对操作系统的等级爱护要求。具体应用形式请参考:ACK等保加固应用阐明。 等保背景常识介绍网络安全等级爱护制度是我国网络安全畛域的基本国策、根本制度。1994 年,国务院公布《计算机信息系统安全爱护条例》147 号令。该条例首次提出“计算机信息零碎履行安全等级爱护”,安全等级爱护理念由此诞生。2007 年和 2008 年,国家颁布《信息安全等级爱护治理方法》和《信息安全等级爱护根本要求》。这被视为“等保1.0”。为适应新技术的倒退,解决云计算、物联网、挪动互联和工控畛域信息系统的等级爱护工作的须要,2019年,由公安部牵头组织发展了信息技术新畛域等级爱护重点规范申报国家标准的工作,等级爱护正式进入“等保2.0”时代。 ACK等保加固的作用以后,ACK集群应用Alibaba Cloud Linux 2 操作系统作为集群默认零碎镜像。为了帮忙ACK的用户“开箱即用”地应用“等保操作系统”,在阿里云云原生团队的反对下,对基于Alibaba Cloud Linux 2 操作系统镜像的ACK集群,在保障原生镜像兼容性和性能的根底上进行了等保合规适配,帮忙用户解脱简单的加固操作和繁琐的配置,让用户享受开箱即用的操作系统等保环境。依照《信息安全技术网络安全等级爱护根本要求(GB/T 22239-2019)》,加固后的零碎满足以下查看项: 查看项类型 查看项名称 危险等级 身份甄别 应答登录的用户进行身份标识和甄别,身份标识具备唯一性,身份鉴别信息具备复杂度要求并定期更换 高 身份甄别 当对服务器进行远程管理时,应采取必要措施,避免鉴别信息在网络传输过程中被窃听 高 身份甄别 应具备登录失败解决性能,应配置并启用完结会话、限度非法登录次数和当登录连贯超时主动退出等相干措施 高 访问控制 应答登录的用户调配账户和权限 高 访问控制 应重命名或删除默认账户,批改默认账户的默认口令 高 访问控制 访问控制的粒度应达到主体为用户级或过程级,客体为文件、数据库表级 高 访问控制 应及时删除或停用多余的、过期的账户,防止共享账户的存在 高 访问控制 应授予治理用户所需的最小权限,实现治理用户的权限拆散 高 访问控制 应由受权主体配置拜访控制策略,拜访控制策略规定主体对客体的拜访规定 高 平安审计 应答审计记录进行爱护,定期备份,防止受到未预期的删除、批改或笼罩等 高 平安审计 审计记录应包含事件的日期和工夫、用户、事件类型、事件是否胜利及其他与审计相干的信息 高 平安审计 应启用平安审计性能,审计笼罩到每个用户,对重要的用户行为和重要安全事件进行审计 高 平安审计 ...

March 5, 2021 · 1 min · jiezi

关于chrome:基于-KubeVela-与-Kubernetes-打造无限能力的开放-PaaS

简介: 本文整顿自阿里云容器技术专家、OAM 标准次要制定者之一、KubeVela 作者和负责人孙健波(天元)在阿里云开发者社区“周二开源日”的直播分享,将分析以后 Kubernetes 利用交付体系存在的问题具体介绍如何基于 OAM 和 KubeVela 体系赋能 PaaS,构建凋谢可扩大又易用的能力。 现在,围绕 Kubernetes 构建利用交付平台曾经逐步成为共识。 Kubernetes 生态自身的能力池诚然是丰盛的,但社区里并没有一个可扩大的、方便快捷的形式,可能帮忙平台团队把这些能力疾速“组装”成面向最终用户的性能(Feature)。因而,只管大家都在基于 Kubernetes 构建下层利用平台,但这些平台实质上并不能与 Kubernetes 生态齐全买通,而是变成一个个的垂直“烟囱”。 有没有办法让平台团队可能在不造轮子、齐全买通 Kubernetes 生态的前提下构建下层平台,从而同时保障平台的易用性和可扩展性呢?本文整顿自阿里云容器技术专家、OAM 标准次要制定者之一、KubeVela 作者和负责人孙健波(天元)在阿里云开发者社区“周二开源日”的直播分享,将分析以后 Kubernetes 利用交付体系存在的问题具体介绍如何基于 OAM 和 KubeVela 体系赋能 PaaS,构建凋谢可扩大又易用的能力。 什么是 KubeVela1. KubeVela 的起源 KubeVela是一个简略易用又高度可扩大的云原生利用治理引擎,是基于 Kubernetes 及阿里云与微软云独特公布的云原生利用开发模型 OAM 构建。 KubeVela 基于 OAM 模型构建了一套具体的实现,通过 Golang 编写,能够端到端地为用户构建云原生利用的平台,提供一个绝对残缺的解决方案。 KubeVela 我的项目自 2020 年 7 月份在社区外面发动,受到包含阿里、微软、Crossplane 等公司工程师在内的宽广社区志愿者的欢送,并一起投入到我的项目开发工作中。他们把在 OAM 实际外面的各种教训与教训,都总结积淀到 KubeVela 我的项目中。 KubeVela 在 2020 年 11 月中旬正式公布,并于公布的第 4 天登顶 Github Go 趋势榜榜首。这个我的项目的魅力在于,一方面我的项目自身比拟容易了解,因为大家刚看到 OAM 公布时,并不知道这个模型可能做什么,然而 KubeVela 提供许多开箱即用的性能以及能够实际操作的 Demo,使得大家更容易了解 OAM 模型以及 KubeVela 利用治理的能力。另一方面是因为许多用户在利用治理方面的诉求越来越强烈,尤其是云原生利用治理。 ...

March 4, 2021 · 3 min · jiezi

关于chrome:Chrome-89-新功能一览性能提升明显大量-DevTools-新特性

明天 Chrome 更新了最新版本 Chrome89,新版本在启动、响应速度上更快,同时 CPU 占用率大幅降落。 比方,提供后退后退缓存(20%的页面可刹时进退)等个性,号称启动速度快了 25%、载入页面速度快了 7%、CPU 占用缩小了 5 倍、可减少额定 1.25 小时续航,内存占用量也优化了。 原文:https://developers.google.com... 上面来具体看看更新了哪些内容。 1. Elements 面板相干更新反对抉择 CSS 的 :target 伪类当初能够应用 DevTools 选中和查看 :target 状态。 在 Elements 面板中,抉择一个元素,能够在右侧切换 :target。 当 URL 中的 hash 和 DOM 元素的 id 雷同时,将触发该元素的 :target 伪类。能够点击这个 Demo 看看成果,这个新的 DevTools 个性能够让你测试这些款式,而不用始终手动更改 URL。 对应 Chromium issue: 1156628 复制 DOM 元素的新选项右键单击元素面板中的一个元素,抉择 Duplicate element,将在其上面疾速创立一个新元素。 或者,你能够应用键盘快捷键复制元素: Mac: Shift + Option + ⬇️Window/ Linux: Shift + Alt + ⬇️ ...

March 4, 2021 · 4 min · jiezi

关于chrome:基于SLS构建RDS审计合规监控

简介: 数据库是企业业务的数据外围,其平安方面的问题在传统环境中曾经成为透露和被篡改的重要本源。因而,对数据库的操作行为尤其是全量 SQL 执行记录的审计日志,就显得尤为重要。背景数据库是企业业务的数据外围,其平安方面的问题在传统环境中曾经成为透露和被篡改的重要本源。因而,对数据库的操作行为尤其是全量 SQL 执行记录的审计日志,就显得尤为重要。SLS联结RDS推出RDS SQL审计性能,将RDS SQL审计日志实时投递到SLS中;SLS提供实时查问、可视化剖析、告警等性能。RDS SQL审计日志记录了对数据库执行的所有操作,这些信息是零碎通过网络协议剖析所得,对系统CPU耗费极低,不影响SQL执行效率。RDS SQL审计日志包含但不限于如下操作:• 数据库的登录和退出操作。• DDL(Data Definition Language)操作:对数据库构造定义的SQL语句,包含CREATE、ALTER DROP、TRUNCATE、COMMENT等。• DML(Data Manipulation Language)操作:SQL操作语句,包含SELECT、INSERT、UPDATE、DELETE等。• 其余SQL执行操作,包含任何其余通过SQL执行的管制,例如回滚、管制等。• SQL执行的提早、执行后果、影响的行数等信息。此外,SLS还针对RDS的操作合规进行监控,及时发现RDS的配置异样,确保数据库安全。 RDS日志审计--采集目前RDS SQL审计日志采集到SLS有两种形式:• 云产品采集渠道长处:大量且同地区实例采集场景下配置简略。毛病:不反对跨地区、跨账号;不反对实例动静发现。如果须要跨地区跨账号,须要自建数据加工工作。• 日志审计渠道长处:反对跨账号、跨地区中心化采集,便于审计报表剖析。反对实例发现,一键开启主动采集;并反对通过采集策略管制采集范畴。毛病:须要AK受权或手动受权来开启日志审计APP。会主动开启采集实例的SQL洞察性能,且不反对主动敞开。如果须要敞开SQL洞察,须要首先整体敞开日志审计RDS采集性能或者通过采集策略管制实例不采集,而后到RDS控制台一一实例敞开SQL洞察。 云产品采集渠道单账号同地区采集场景(只能将RDS审计日志采集到同地区的日志库中)• SLS控制台首页“接入数据”区域,抉择“RDS 审计”。下文以采集张家口实例为例阐明。 • 因为采集的实例位于张家口,所以须要在张家口新建或者抉择已存在的project及logstore。• 留神:采集的RDS实例审计日志仅反对同地区采集。 • “数据源配置”页,实现RAM受权后能够查看张家口所有的RDS实例信息,默认日志投递性能是敞开的。之后能够依据日志采集需要,勾选相应的“开明投递”按钮,开启对应实例的日志投递性能。 • 至此就实现了SQL审计日志的采集开启,跳转到上述配置的logstore下即可查看RDS实例日志。 跨地区、跨账号采集场景因为云产品采集渠道有只能将RDS审计日志采集到同地区的日志库的限度,所以要突破这个限时实现跨账号跨地区采集,就必须要自建跨域或者跨账号数据加工工作。因为自建数据加工工作须要比较复杂的受权,这里不再具体介绍。如有须要,详见:1、配置自定义角色受权2、最佳实际:跨地区传输数据3、最佳实际:多指标Logstore数据散发 中的“跨账号散发”局部。 由此可见,云产品采集渠道仅仅在简略采集场景下具备便捷采集的劣势,然而在解决跨地区、跨账号采集时不仅数据同步链路较长,而且还须要比较复杂的受权过程;而且当实例变更(甚至新的实例呈现)时,须要手动保护同步链路,保护老本极高。而日志审计渠道恰好能够很好的解决跨地区、跨账号采集,实例变更保护老本高的痛点。 日志审计采集渠道日志审计受权倡议应用阿里云RAM用户操作。• 创立阿里云RAM用户,并赋予该用户AliyunRAMFullAccess、AliyunLogFullAccess权限,创立AK。• 登录上述RAM用户,在SLS控制台抉择“日志审计服务”。 • 首次进入须要进行受权能力开启。这里输出第一步创立的AK,并抉择审计日志存储的核心Project地区即可。 • 如果呈现如下页面阐明曾经受权实现。之后就能够依据采集日志的须要开启对应的云产品日志,例如这里须要采集操作审计(Actiontrail)日志及RDS SQL审计日志。 配置SQL审计采集本文重点形容如何开启RDS SQL审计日志并通过采集策略管理日志采集范畴。SQL审计日志开启首先须要进行采集策略配置。残缺的语法阐明详见采集策略文档。这里列出一些罕用的策略计划。• 采集特定区域的实例日志。例如:只采集杭州、上海的实例。 • 不采集特定标签的实例。例如:给测试实例打上type标签取值test。 • 只采集限定的实例日志。 SQL审计 RDS日志审计--报表基于SLS的SQL审计日志提供了3张审计报表:• RDS审计核心:次要展示了所有数据库的SQL执行指标、散布、趋势等信息。例如:PV、UV、操作数据库/数据表等的统计。• RDS审计平安核心:次要展示了所有数据库的失败SQL和危险SQL,以及大批量删除或批改事件的详情、散布和趋势等。• RDS审计性能核心:次要展示了所有数据库的具体性能指标,例如SQL执行峰值、SQL执行的均匀工夫、慢SQL的具体散布与起源等。 ...

March 1, 2021 · 2 min · jiezi

关于chrome:工具像大佬一样使用-Google

原文地址: Use Google like a pro 原文作者:Marko Denic 译者:Gopal 译者注:本文篇幅十分短,但集体感觉对本人有所帮忙,所以打算分享一下。对于墙内墙外的问题,笔者因为目前在一家小外企,所以能够解决。不过也是有其余的解决方案的,有条件的开发者还是倡议应用 Google对于开发者而言,应用 Google 是最重要的一项技能之一 让我给大家展现如何更好的应用 Google 吧! 开始吧~ 1. 应用引号强制进行准确匹配搜寻"what is javascript" 2. And 运算符And 运算符只会返回和它们都相干的搜寻后果 html AND css 3. 应用 OR 操作符获取搜索词中某一个的后果(javascript OR python) free course 4. - 操作符将排除蕴含搜索词的后果 javascript -css 5. 能够应用(*)通配符作为占位符,它将被任何单词或短语替换"how to start * in 6 months" 6. 在一个繁多的网站搜寻site:freecodecamp.org 7. 查找特定的文件类型filetype:pdf learn css 8. 搜寻一个数字范畴ecmascript 2016..2018 如果你喜爱这篇文章,肯定要记得点赞~ 开心编程吧~

March 1, 2021 · 1 min · jiezi

关于chrome:chrome-extension开发实战之QQ空间助手

原文地址: https://segmentfault.com/a/11...转载请在文首注明起源TL;DR 背景介绍需要剖析常识储备文档举荐构造组成组件通信开发调试打包公布问题解决背景介绍本文历时较久,2020年写了一半,写到迷茫,索性搁置,2021年翻出来持续写的;通过了半年多的工夫再看,会有一些不一样的了解,存在局部配图格调不统一.然而我会确保内容的正确和表白的统一.2020年的某一天我把之前写的QQ空间批量删除说说&留言的脚本写了个chrome插件版,名字也改成了QQ空间小助手.因为也是第一次写插件,所以记录这个过程,分享开发过程和期间遇到的问题,并做一些关键点的梳理.所以,这并不是一篇大而全的chrome extension开发教程,这是一篇以QQ空间助手为实战来切入插件开发然而偏重讲chrome extension开发的文章. 需要剖析QQ空间小助手性能很简略,外围性能(其实也就这点性能)是批量删除qq空间的说说和留言.实现上也很简略,只须要两个步骤. 获取说说或者留言列表顺次遍历id删除说说或者留言这外面的艰难一个在于找到获取&删除 留言和说说 所须要的参数(这个咱们不开展介绍),另外一个艰难是这些性能怎么在chrome extension中实现. 依据下面这些需要,我了解大略操作流程是这样的, 点击icon,或者点击icon弹出来的页面而后就开始获取列表,而后遍历列表开始删说说. 外面大略须要用到,组件,组件间通信这些内容. 然而因为是没有接触过这块,所以得搞清楚都须要有什么常识储备,那就先从这里开始介绍. 常识储备整体上,插件开发这个货色没那么难,须要的技术也比较简单.基本上就是前端那些常识: JavaScriptHTML + CSS外加一些软技能 chrome devtools的应用和根本的调试能力文档浏览能力基本上做过我的项目的前端都能hold住. 如果你在开发之前有些不确定的问题的话须要提前理解的话,也能够看这篇文档高频问题Q&A. 介绍完了常识储备,咱们就得看文档了. 文档举荐开发文档举荐看这份官网文档 加上一些 官网demo. 接触新的技术,文档必定是不可少的,然而网上各种教程 + 文档,泥沙俱下,咱们到底应该看教程还是看文档.我集体了解是,不论教程还是文档,都能够看,然而要优先看官网的文档和教程,看一手的材料,因为我看文档的过程中发现,非官方的货色(非一手文档)信息传播不残缺,甚至有纰漏.所以尽着官网的来,除非有很好的非官方教程或者其余的起因.也有一份非官方文档不错,然而不举荐间接看,倡议联合官网文档作为对照来看,因为我在开发的时候发现这份文档有些内容和官网最新的文档不统一(比方对于browser action和page action的定义). 另外,在理论的浏览过程中,还会有些中央看文档看不明确的,这时候有针对的搜一些博客/教程就能够.比方这次组件通信的中央有困惑,就找了些不错的文档看. 一篇文章教你顺利入门和开发chrome扩大程序(插件)(文章中的代码有笔误,不要间接拿来用)Chrome插件中 popup,background,contantscript消息传递机制还有一些别的文章,都整顿下来能够参考. 官网文档(举荐) | 官网Demo举荐的非官方文档插件通信相干辅助 一篇文章教你顺利入门和开发chrome扩大程序(插件)Chrome插件中 popup,background,contantscript消息传递机制其余 Chrome插件开发全攻略调试相干 | Debugging extensions打包公布相干 | 创立和公布自定义 Chrome 利用和扩大程序看完文档咱们大抵会失去一些信息.上面就来讲讲. 构造组成UI组成在这一部分你只须要理解一个插件会由哪些局部组成就能够了,具体性能前面介绍. 失常状况下咱们看到的浏览器和插件大略长这样 当咱们鼠标点击插件icon之后就变成了这样 从下面的图上来看,次要由 icon(任务栏的图标) 和 点击之后的弹窗两个大件组成,局部插件还会有一个专门的用于配置的页面(这里没用到,就不介绍了).另外,在UI之外,还会background和content_script存在.再加上这两个重要的概念之后整个构造就是这样的 上面看看文件构造. 文件构造文件构造比拟能直观的反馈组件的组成和性能.从文件构造来看。个别一个插件的文件构造长这样的(之所以说个别是因为不是每个插件都能用到全副的性能). qzone_helper_extension│ background.js│ manifest.json│ popup.html│ popup.js│ qq_icon.png└─ content_script.js其中各个文件的性能如下: manifest.json是咱们最先须要理解的局部,这个文件的性能相似于package.json文件,这里定义插件的配置信息,这些信息小到插件名称,图标,版本号等形容信息,大到你须要申请的权限和各种引入的资源,入口文件等重要配置。所以这里应该是咱们最先须要理解的局部。qq_icon.png是最不值得咱们了解的局部,这就是个图标文件而已。popup.html是比拟直观的一个文件,这个就是你点击插件图标之后弹出来的界面,那个界面是html写的,同样的,对应的popup.js用来解决popup页面的交互和popup模块和别的模块之间的通信。background.js和content_script.js是外围.其中,background.js能够了解为我的项目的app.js文件,而content_script.js是和网页是一伙的,能够简略的了解为是咱们在网页那边的代理,帮咱们做些网页相干的操作.加上这些构造和文件之间的对应关系是这样的 到这里,你大略理解的一个插件的根本组成构造.理解完构造,咱们分来看看各局部的具体情况. 插件各局部性能Icon(按钮)一般来说,Icon是咱们插件的性能入口,也能够显示一些徽标.在chrome插件中,这种icon按钮是分两种的: page actionbrowser action他们的区别与应用场景如下 ...

February 27, 2021 · 3 min · jiezi

关于chrome:Javascript性能优化内联缓存-V8引擎特性

javascript 是单线程、动静类型语言,那么咱们在编码时候如何编写性能最优代码呢?上面将解说V8引擎的内联优化。利用内联缓存这个个性咱们能够编写更加优良的代码。什么是内联缓存援用官网的形容:内联缓存(Inline caching)是局部编程语言的运行时零碎采纳的优化技术,最早为Smalltalk开发。内联缓存的指标是通过记住以前间接在调用点上办法查问的后果来放慢运行时办法绑定的速度。内联缓存对动静类型语言尤为有用,其中大多数(如非全副)办法绑定产生在运行时,因而虚办法表通常无奈应用。 咱们能够了解为javascript每一次的栈执行遇到调用内部函数、对象时候都产生地址缓存记录,下回执行到这个地位时候间接从缓存中取出对应记录,省去从新查找这一过程从放慢程序执行速度。转换成代码模拟计算逻辑(伪代码)为了更好提现呈现内联缓存的优化,咱们把对象所有办法逻辑为统一。 let value = 0 const Calculator = { add1(val) { value += val }, add2(val) { value += val }, add3(val) { value += val }, add4(val) { value += val }, add5(val) { value += val }, add6(val) { value += val }, add7(val) { value += val }, add8(val) { value += val }, add9(val) { value += val }, add10(val) { value += val } }不实用内联优化策略的代码 function notOptimization(val, type) { Calculator[type](val) // 动静执行函数,以后调点无奈确定地址 } const CalculatorKey = Object.keys(Calculator) console.time('notOptimization') for(let i = 0; i < 1000000; i ++) { const key = CalculatorKey[Math.floor(Math.random() * CalculatorKey.length)] notOptimization(1, key) } console.timeEnd('notOptimization')下面这段代码应用哈希疾速查找对应函数,然而放弃内联缓存策略。代码5次执行后果,均匀为80ms左右 ...

February 23, 2021 · 1 min · jiezi

关于chrome:nodejs代码如何进行断点调试

nodejs代码如何进行断点调试呢?作为一名服务端开发人员,对代码进行断点调试是最根本的能力,接下来我简略介绍两种调试形式,一种是依赖于编辑器工具,另外一种是依赖于chrome浏览器(两种形式均在已装置nodejs前提下)。 一、应用vscode编辑器关上编辑器,新建一个我的项目vscode-debugger-test,创立两个文件:app.js:test.js: 如果想调试test.js中log这个办法,那么首先应该当初我的项目的根目录创立一个.vscode文件夹,而后再.vscode这个文件夹下创立一个名字为launch.json的文件: 接下来就是编写这个json文件: launch.json { // 配置名称,将会在启动配置的下拉菜单中显示 "name": "test", // 配置类型 "type": "node", // 申请配置类型,能够为launch(启动)或attach(附加) "request": "launch", // 将要进行调试的程序的门路 "program": "${workspaceFolder}/app.js", // 程序调试时传递给程序的命令行参数,个别设为空即可 "args": [], // console执行形式 1、integratedTerminal 编辑器外部终端执行 2、externalTerminal 内部终端执行 "console": "integratedTerminal"}编辑好了,开始调试,首先在test.js文件log函数外部第一行的最前端加上断点, 而后点击编辑器右边的运行,而后再点击运行按钮,开始运行,这时候就能看到曾经进入断点了,而后就能够像在浏览器中调试js那样,欢快的调试nodejs了,点击这里能够进行跳过断点、进行调试、单步跳过、单步调试等操作。 参考:官网launch.json配置阐明 二、应用Chrome的inspect调试还是应用上边vscode-debugger-test这个我的项目作为demo,但要对app.js文件略微做下革新: test.js文件,加一行代码: 接下来,在终端运行 node --inspect=9229 app.js 启动之后,在浏览器地址栏输出http://localhost:9999/,显示如下: 此时,新关上一个Chrome标签页,地址栏输出chrome://inspect/#devices 能够看到,这时候这里呈现了一个链接,点击进入Chrome控制台,而后刷新http://localhost:9999/,这时候就进入了断点的中央: 到这里曾经十分相熟了,就像调试js一样调试就能够了。

February 22, 2021 · 1 min · jiezi

关于chrome:5个不常提及的HTML技巧

2021年你须要晓得的HTML标签和属性Web开发人员都在宽泛的应用HTML。无论你应用什么框架或者抉择哪个后端语言,框架在变,然而HTML始终如一。只管被宽泛应用,但还是有一些标签或者属性是大部分开发者不熟知的。尽管当初有很多的模版引擎供咱们应用,然而咱们还是须要尽可能的熟练掌握HTML内容,就像CSS一样。 在我看来,最好尽可能应用HTML个性来实现咱们的性能,而不是应用JavaScript实现雷同的性能,只管我抵赖编写HTML可能会是反复的和无聊的。 只管许多开发人员每天都在应用HTML,但他们并没有尝试改良本人的我的项目,也没有真正利用HTML的一些鲜为人知的个性。 上面这5个通过HTML标签/属性实现的性能我感觉须要理解一下: 图片懒加载图片懒加载能够帮忙晋升网站的性能和响应能力。图片懒加载能够防止立刻加载那些不在屏幕中立刻显示的图片素材,当用户滚动邻近图片时再去开始加载。 换言之,当用户滚动到图片呈现时再进行加载,否则不加载。这就升高了屏幕内容展现过程中的图片素材的申请数量,晋升了站点性能。 往往咱们都是通过javascript来实现的,通过监听页面滚动事件来确定加载对应的资源。然而,在不齐全思考兼容性的场景下,咱们其实能够间接通过HTML来间接实现。 注:本篇的提到的标签和属性的兼容性须要大家依据理论场景来选取是否应用能够通过为图片文件增加loading="lazy"的属性来实现: <img src="image.png" loading="lazy" alt="lazy" width="200" height="200" />输出提醒当用户在进行输出搜寻性能时,如果可能给出无效的提醒,这会大大晋升用户体验。输出倡议和主动实现性能当初到处可见,咱们能够应用Javascript增加输出倡议,办法是在输入框上设置事件侦听器,而后将搜寻到的关键词与预约义的倡议相匹配。 其实,HTML也是可能让咱们来实现预约义输出倡议性能的,通过<datalist>标签来实现。须要留神的是,应用时这个标签的id属性须要和input元素的list属性统一。 <label for="country">请抉择喜爱的国家:</label><input list="countries" name="country" id="country"><datalist id="countries"> <option value="UK"> <option value="Germany"> <option value="USA"> <option value="Japan"> <option value="India"> <option value=“China”></datalist>Picture标签你是否遇到过在不同场景或者不同尺寸的设施下面的时候,图片展现适配问题呢?我想大家都遇到过。 针对只有一个尺寸的图片素材的时候,咱们往往能够通过CSS的object-fit属性来进行裁切适配。然而有些时候须要针对不同的分辨率来显示不同尺寸的图片的场景的时候,咱们是否能够间接通过HTML来实现呢? HTML提供了<picture>标签,容许咱们来增加多张图片资源,并且依据不同的分辨率需要来展现不同的图片。 <picture> <source media="(min-width:768px)" srcset="med_flower.jpg"> <source media="(min-width:495px)" srcset="small_flower.jpg"> <img src="high_flower" style="width: auto;" /></picture>咱们能够定义不同区间的最小分辨率来确定图片素材,这个标签的应用有些相似<audio>和<video>标签。 Base URL当咱们的页面有大量的锚点跳转或者动态资源加载时,并且这些跳转或者资源都在对立的域名的场景时,咱们能够通过<base>标签来简化这个解决。例如,咱们有一个列表须要跳转到微博的不同大V的主页,咱们就能够通过设置<base>来简化跳转门路 <head> <base href="https://www.weibo.com/" target="_blank"> </head><body> <a href="jackiechan">成龙</a> <a href="kukoujialing">贾玲</a></body><base>标记必须具备href和target属性。 页面重定向(刷新)当咱们心愿实现一段时间后或者是立刻重定向到另一个页面的性能时,咱们能够间接通过HTML来实现。 咱们常常会遇到有些站点会有这样一个性能,“5s后页面将跳转”。这个交互能够嵌入到HTML中,间接通过<meta>标签,设置http-equiv="refresh"来实现 <meta http-equiv="refresh" content="4; URL='https://google.com' />这里content属性指定了重定向产生的秒数。值得一提的是,只管谷歌声称这种模式的重定向和其余的重定向形式一样可用,然而应用这种类型的重定向其实并不是那么的优雅,往往会显得很突兀。因而,最好在某些非凡的状况下应用它,比方在长时间用户不流动之后再重定向到指标页面。 后记HTML和CSS是十分弱小的,哪怕咱们仅仅应用这两种技术也能创立出一些微妙的网站。尽管它们的使用量很大很广泛,还是有很多的开发者并没有真正的深刻理解他们,还有很多的内容须要咱们深刻的去学习和了解,实际,有很多的技巧期待着咱们去发现。

February 20, 2021 · 1 min · jiezi

关于chrome:Chrome-OS-去年市场占有率大涨引开发者们重视

来自IDC的最新数据显示,2020年 Chrome OS 电脑的销量首次超过 macOS 电脑 ,市场份额大幅增长,而 Windows 却大幅度下滑。 这个数据证实谷歌获得肯定的胜利,对苹果和微软来说是一个正告。但最重要的是向应用程序和游戏开发者发出信号,Chrome 操作系统不应再被疏忽,换句话说任何互联网产品或服务的公司都应预留资源,确保 Chrome 操作系统的体验可与 Windows 和 macOS 等量齐观。 数据分析2020年第一季度,苹果和谷歌并驾齐驱:Windows占据了87.5%的市场份额,macOS占据了5.8%的市场份额,Chrome OS占据了5.3%的市场份额。然而在2020年第二季度,Windows降落至81.7%,macOS增长至7.6%,Chrome OS跃升至10.0%。 2020年第三季度和2020年第四季度趋势更加显著:Windows在第三季度进一步降落至78.9%,而后在第四季度降落至76.7%;macOS在第三季度增长到8.4%,而后在第四季度回落到7.7%,而Chrome OS在第三季度占11.5%,而后在第四季度占14.4%。 以下是按年细分: Windows:降落4.9点,从2019年的85.4%降落到2020年的80.5%Chrome操作系统:增长4.4点,从2019年的6.4%到2020年的10.8%macOS:回升0.8点,从2019年的6.7%到2020年的7.5%间断三个季度Chrome OS高于macOS成为一种趋势。能够说,宏碁、华硕、戴尔、惠普和联想等PC厂商的Chromebook当初曾经超过了苹果的一系列台式机Mac和笔记本MacBook。 在经验了多年降落后,PC 出货量在2019年逆转场面,开始增长,却因为新冠病毒的忽然暴发,在2020年第一季度产生大幅度下滑。好在2020年第二季度和剩下的工夫里,供给缓和问题失去解决,近程办公和在线教育的衰亡推动了企业和消费者的PC需要。 其实 Chrome OS在过来几年始终在增长,所以2020年增长放慢并不太奇怪。值得关注的问题是这种增长是否会持续,又是否会以就义Windows为代价?尽管PC出货量全面回升,但 macOS的份额也在一直减少,而Windows几十年来首次跌破80%的门槛。 Chrome OS挑战Windows在低成本笔记本市场的统治位置,是传统PC销量更大反弹的一部分,也是微软将Windows 10X转移到最后在单屏设施上首发的起因之一。在疫情之前,Chrome操作系统的胜利次要限于美国学校。2020年的需要仿佛曾经扩充到美国PC市场这一很小但至关重要的局部,将来Chrome 操作系统有很大可能份额持续上涨,扩大到美国以外的市场。

February 18, 2021 · 1 min · jiezi

关于chrome:人生第一个扩展Github1s

1 灵感某天看到了一个叫github1s的仓库: 基于Node.JS、Yarn、Python等技术栈,在github.com下面加上“一秒”,也就是github1s.com,就能在VSCode中关上该仓库,十分好用。 同时笔者装置有一个叫Sourcegraph的扩大,就是上面这个: 用过的同学都晓得这个扩大是干嘛的,于是笔者就想相似的在这个扩大旁边加一个超链接的扩大间接关上github1s.com,效果图曾经在下面了,点击那个VSCode的图标就能够间接关上。 2 入手因为笔者并没有扩大开发的教训,因而先去看了一下Chrome扩大开发的文档并留下了一篇基础教程博客,而后就能够开始入手了,我的项目构造如下: 3 图标对于图标,其实是花了一点工夫的,比方,受到该仓库的影响,一开始定的图标是上面这样子的: 而后想了一下如同不太对劲,就改成了这样子的: 至于在扩大治理中显示的图片,改成了一个比较简单的: 这样图标的问题就解决了。 4 显示下一步就是增加性能到扩大中并且让其显示在Sourcegraph的旁边,首先manifest.json如下: { "name": "Github1s", "description": "One second to read GitHub code with VS Code.(https://github.com/conwnet/github1s)", "version": "1.0", "manifest_version": 3, "content_scripts": [{ "matches": ["https://github.com/*/*"], "js": ["/js/icon.js","/js/init.js"] }], "action": { "default_icon": { "16": "/icons/logo16.png", "32": "/icons/logo32.png", "48": "/icons/logo48.png", "128": "/icons/logo128.png" } }, "icons": { "16": "/icons/logo16.png", "32": "/icons/logo32.png", "48": "/icons/logo48.png", "128": "/icons/logo128.png" }}解释一下content_scripts,当匹配到matches中的URL时,便会主动执行js外面的脚本,先来看一下init.js,这个脚本的作用就是增加把图标增加到Sourcegraph的旁边: ...

February 13, 2021 · 1 min · jiezi

关于chrome:Chrome扩展开发基础教程附HelloWorld

1 概述Chrome扩大开发的基础教程,代码基于原生JS+H5,教程内容基于谷歌扩大开发官网文档。 2 环境Chrome 88.0.4324.96Chromium 87.0.4280.141Brave 1.19.84FireFox 85.0WebStorm 2020.3.2Manifest V33 开发环境筹备开发扩大倡议应用WebStorm,举荐WebStorm的起因是可能补全,在设置中的Libraries中能够下载chrome的库,这样就可能补全了: 另一个倡议应用的是VSCode,然而笔者目前没有找到让VSCode补全的形式,心愿晓得的能够在评论指出补充一下。 当然其实扩大开发并没有规定应用哪一个IDE,罕用的Web开发IDE比方HBuilder也是能够的,看集体爱好了。 4 创立manifest.json首先创立一个空白文件夹: mkdir FirstExtensioncd FirstExtension接着创立一个叫manifest.json的文件,间接在WebStorm中创立即可,文件内容如下: { "name": "First Extension", "description": "This is my first extension", "version": "1.0", "manifest_version": 3}关上浏览器进入治理扩大程序,并开启开发者模式,抉择Load unpacked,关上方才创立的FirstExtension文件夹: 这样就能够看到扩大了。 事实上最简略的扩大只须要一个manifest.json,来形容扩大最根本的一些属性以及行为,因而这样就算实现HelloWorld了。 5 增加弹出界面当初扩大什么界面也没有,当初能够尝试着给扩大增加一个点击就弹出的界面,首先批改manifest.json,增加action: { "name": "First Extension", "description": "This is my first extension", "version": "1.0", "manifest_version": 3, "action": { "default_popup": "popup.html" }}在与manifest.json同级目录下创立popup.html文件: <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title></head><body> <h1>Hello World!</h1></body></html>这样点击扩大就会弹出对应文字了: 6 增加图标在manifest.json中增加icons字段: { "name": "First Extension", "description": "This is my first extension", "version": "1.0", "manifest_version": 3, "action": { "default_popup": "popup.html" }, "icons": { "16": "icons/16.png", "32": "icons/32.png", "48": "icons/48.png", "128": "icons/128.png" }}图标文件能够从文末的源码处获取,从新加载后就能够看到扩大的图标扭转了。 ...

February 12, 2021 · 1 min · jiezi

关于chrome:电商直播平台如何借助容器与中间件实现研发效率提升100

简介: 通过理论场景验证及用户的综合评估,电商直播平台借助全面的云原生容器化能力和中间件产品能力,大幅晋升开发部署运维效率达50%~100%,极大地晋升了用户体验,为业务继续倒退打下了松软的根底。前言直播带货是近期倒退十分迅猛的一种新的电商模式。构建一个电商直播平台从技术角度上大抵能够分为视频直播服务、CDN、前端(H5/小程序)、大数据、以及各种业务后盾,如直播互动、商家和经营平台等。相比于传统的电商零碎,电商直播平台有一些相似的中央,如零碎须要具备高并发的能力来应答流量洪峰;但同时直播业务也有一些独有的个性: 直播业务的潮汐个性,须要更强的弹性能力及老本优化计划。微服务化后,要求更高的开发效率,以及更精细化的流量管制。直播互动有着十分高的实时性,零碎须要具备前后端监控一体化的能力。直播业务波及到前期音视频的解决须要正当调配计算资源。能够看到上述个性都是一些非业务性的需要,为了达成这一目标,企业须要在IDC额定投入大量的人力进行基础设施的建设和保护。目前,越来越多的企业曾经迁徙到云平台或者正在向云平台迁徙的过程中,如果能将这些非业务性能下沉,利用云平台提供的产品&技术来承接这些能力的话,企业就齐全能够专一于业务自身,实现疾速迭代、独立高效、加重老本。 云原生架构正是为此而生。  什么是云原生架构?云原生架构是基于云原生技术的一组架构准则和设计模式的汇合,旨在将云利用中的非业务代码局部进行最大化的剥离,从而让云设施接管利用中原有的大量非性能个性(如弹性、韧性、平安、可观测性、灰度等),使业务不再有非功能性业务中断困扰的同时,具备轻量、麻利、高度自动化的特点。 为实现云原生架构,必然须要依靠于各种云原生理念、实际及技术,即云平台所提供的容器、微服务、DevOps、Service Mesh、Serverless和中间件等服务。从CNCF的定义来看,采纳基于云原生的技术和治理办法,将更好地把业务生于“云”或迁徙到云平台,从而享受“云”的高效和继续服务能力。 电商直播须要哪些云原生解决方案?电商直播平台零碎为了满足业务的疾速倒退,须要具备一些额定能力(当然这里可能只是一部分),咱们临时以这些为例,将需要进一步总结形象,大抵能够演绎为以下几点:  极致弹性和老本; 微服务治理及流量管制; 立体化监控; 音视频解决自动化,计算资源按需应用。为解决以上痛点,接下来围绕电商直播平台,具体介绍在一些典型的业务场景下,阿里云提供的一整套云原生解决方案。 容器服务ACK解决对老本和极致弹性的诉求传统架构在应答“电商直播”这种旧式互联网化业务时,经常面临公布迭代效率低、高峰期扩容慢、运维复杂度高三大痛点。同时直播业务有典型的霎时流量冲击问题,无奈无效预估峰值,并且顶峰期间对提早敏感,通过扩容K8s Node节点计划无奈满足业务需要。 直播业务能够借助阿里云容器服务ACK + VK (Serverless ECI基础设施)架构,解决直播业务对老本和极致弹性诉求,具体体现在: 研发效率晋升100%;运维资源根本解放;弹性Serverless ECI,资源老本升高60%~70%。同时通过纳管注册状态,能够实现将其余云平台和IDC自建K8s集群进行对立治理,帮忙客户抹平了多云架构中日志采集、监控等运维治理的差异性,大幅晋升了整体运维效率。 微服务引擎MSE提供全面的微服务治理计划在直播过程中,商家和观众进行互动下单,直播前端和后盾业务零碎进行频繁的交互。直播的后盾业务零碎采纳微服务+容器的架构,业务零碎依据不同的模块(如店铺、商品、订单)曾经进行了微服务拆分。同时为了满足业务须要,业务零碎须要具备流量管制的能力,即对某些微服务进行了多版本的部署,并将特定的用户申请引流到某个特定版本进行解决。 家喻户晓,零碎采纳微服务化部署后,调用链路变得复杂。此外在容器环境下,POD IP的不固定性等因素都为实现流量管制带来肯定的难度。咱们能够采纳阿里云微服务引擎(MSE)提供的微服务治理计划。 微服务引擎MSE为微服务利用提供全面的微服务治理计划,包含服务鉴权、无损下线、离群实例摘除、服务降级、金丝雀公布、标签路由等性能。其中标签路由性能能够简略完满地实现在K8s环境下流量管制的能力。微服务公布过程中,只需编辑YAML文件增加自定义标签,同时在MSE控制台将申请参数(如http header等)和此前创立的标签进行绑定即可。 通过此计划,不仅能够在生产环境中无侵入性地解决了流量管制的问题,在开发测试环境中,也可将标签路由性能利用在分支测试等场景。 ARMS提供残缺立体化全链路监控计划电商直播零碎包含H5页面和小程序前端层、微服务应用层、中间件层(MQ、Redis等)、数据库层以及根底资源层等,零碎中任何一个环节出问题都可能导致一条业务申请出现异常。联合业务需要,运维效率、资源老本等因素,部署在云上的利用能够通过阿里云利用实时监控服务(ARMS) 为直播业务提供一套残缺的立体化的全链路监控计划。 ARMS畛域全景图 在直播场景下,ARMS提供的性能解决了诸如以下几个理论问题: 在直播过程中,如果用户在前端进行下单等操作产生谬误,利用ARMS提供的前后端链追踪性能,可将前端与后端串联起来,实现一站式的问题排查。零碎中呈现慢调用后,须要对整个链路中的瓶颈进行定位,而这个瓶颈可能呈现在网络延时、微服务利用外部,或者利用所依赖的缓存和数据库等组件,开发运维人员能够借助ARMS提供的白屏化链路监控、问题诊断等能力来疾速定位。在ARMS控制台为外围业务及资源配置了欠缺的监控报警能力,通过短信、钉钉、Webhook等形式推送给工程师进行第一工夫排查,及时发现问题缩小业务损失。 阿里云函数计算解决自动化及效率等问题在直播平台发动的直播完结后,通常会有一些回放视频须要进行一些解决,比方对视频进行转码,或其余解决后再进行二次散发。通常为了实现这一个性能,咱们须要自建转码服务器,但因为直播业务人造的潮汐属性,大部分工夫这些转码服务器处于闲置阶段,无奈实现计算资源的最大利用和老本最优化。 阿里云函数计算 FC 事件触发机制完满第解决了自动化及资源利用率等问题。开发人员能够将转码逻辑部署到函数计算,配置OSS事件触发器,当有新的直播回放视频上传到OSS后,可主动触发函数计算进行转码及散发。 此计划具备的劣势是: 疾速上线: 用户基于FFmpeg自建的转码服务,外面很多命令参数都是线上实际很好的参数,函数计算反对用户命令无缝迁徙, FFmpeg的版本也能够自定义。弹性高可用:计算力不再是瓶颈,迅速调动大量计算资源进行减速、并行转码。降低成本: 视频转码是CPU密集型,基于函数计算按需付费,能大大降低转码老本。 总结联合下面所探讨的内容,咱们再来看下采纳阿里云云原生解决方案后,一个残缺的电商直播平台的部署架构如下: 通过理论场景验证及用户的综合评估,电商直播平台借助全面的云原生容器化能力和中间件产品能力,大幅晋升开发部署运维效率达50%~100%,极大地晋升了用户体验,为业务继续倒退打下了松软的根底。 作者:鹿玄,阿里云解决方案架构师原文链接本文为阿里云原创内容,未经容许不得转载

February 10, 2021 · 1 min · jiezi

关于chrome:Mac上本地编译Chrome浏览器踩坑笔记202102最新

科普:Google Chrome浏览器是基于开源我的项目Chromium构建的,因而Chromium我的项目构建进去的产物就是Chrome浏览器本尊。环境依赖首先,请确保你的网络环境可能拜访到Google面向开发者的服务,包含但不限于: *.http://appspot.com*.http://github.com*.http://googlesource.com*.http://googleapis.com整个过程中99%以上的报错,根本原因都是这个。 其次,确保你的Mac电脑满足以下要求: 非ARM版 Mac零碎版本:10.15.4+xcode版本:12.2+(因为编译过程依赖xcode提供的clang编译器)macOS 11.0 SDK,这个能够通过运行 ls xcode-select -p/Platforms/MacOSX.platform/Developer/SDKs 来确认下载编译工具链:deptooldeptool是下载和编译chromium我的项目的工具套件,编译v8等其余google的开源我的项目也同样实用。 应用 git 把 deptool 工具我的项目克隆到本地: git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git此时fetch、gclient等命令行工具其实曾经能够通过绝对路径拜访并执行了,不过为了后续操作不便,能够将其退出到你的 ~/.zshrc 里: export PATH="$PATH:/path/to/depot_tools"实现后,在命令行里测试下 fetch 命令是否可用: which fetch下载Chromium我的项目代码因为chrommium我的项目历史悠久,git仓库微小无比,为更快的实现下载代码,能够疏忽历史提交代码的形式拉取: fetch --no-history chromium国内的网络还是可能因不稳固因素导致拉取中途失败,没关系,遇到网络等起因拉取失败时,能够以此命令持续断点续传: gclient sync通过重复断点续传,最终实现下载,就能够开始本地编译了~ 无关编译Google的C++我的项目大多应用ninja这样一个跨平台的编译工具,在mac端ninja底层会调用苹果公司的clang编译器。 因为ninja的编译参数较为简单,Google又提供了gn 这样一个工具用于 依据以后零碎环境生成适合的ninjaFile,尔后应用autoninja进行编译时就不必设置任何参数了,间接基于ninjaFile配置文件进行编译。 具体过程如下: gn gen out/Default当初会在out目录下生成编译Chrome所需的一系列参数和配置,而后开始编译(整个过程大略耗时4-5个小时): autoninja -C out/Default chrome其实当初autoninja的编译速度曾经比以前快多了,几年前我第一次编译chromium,应用过后简陋的官网文档一步一个坑踩过去,编译一遍要花一夜的工夫,甚至被mac的风扇声吵得不得不行...编译实现后,你会看到在out目录下呈现了 ./out/Default/Chromium.app/Contents/MacOS/Chromium 这样一个可执行文件,间接命令行执行即可,就会关上你本人本地编译的Chromium了,首次关上速度较慢 Mac端的C++代码入口文件是这个: src/chrome/app/http://chrome_exe_main_mac.cc 你能够在此文件中 std::cout 打印输出到stdout,但因为chrome是多过程架构,子过程中无奈间接进行输入或调试。 无关调试的内容,能够关注本专栏:Web开发技术底细 另外,欢送对抓取方面感兴趣的敌人关注我的一个开源我的项目webster, 我的项目以Node.js 联合Chrome headless模式实现了一个高可用性网络爬虫抓取框架,借以chrome对页面的渲染能力, 能够抓取一个页面中 所有的js及ajax渲染的异步内容;并联合redis实现了一个工作队列,使得爬虫程序能够不便的进行横向、纵向的分布式扩大。部署起来很不便,我曾经为webster提供了一个官方版的根底运行时docker镜像,如果你想先睹为快也能够试试这个webster demo docker镜像。 参考起源本文中的踩坑笔记来自于: 官网文档:如何获取chromium源代码 官网文档:Mac端编译Chromium我的项目指南

February 7, 2021 · 1 min · jiezi

关于chrome:JSCSS自适应屏幕

布局适配形式Media Query(媒体查问):当初比拟支流的适配计划,可依据视口不同编写不同款式达到适应成果,比方框架Bootstrap,它能实现大部分我的项目需要,然而编写过于简单。flex布局:支流的布局形式,不仅实用于挪动Web,网页上也体现良好,也是当初应用最多的布局形式。固定高度,宽度百分比:这种办法只适宜简略要求不高的webApp,个别在适应要求不高,或者大屏显示没有要求时候能够应用。rem 单位介绍rem(font size of the root element)是绝对长度单位。绝对于根元素(即html元素)font-size计算值的倍数原理:将px替换成rem,在脚本中应用JS动静批改html的font-size适配,它能够依据根视口大小去扭转基准元素的字体,而后进行等比缩放来进行变动,达到各种屏幕适应。管制的JS写法var htmlWidth = document.documentElement.clientWidth || document.body.clientWidth; //获取屏幕的宽度//获取HTML的Dom元素var htmlDom = document.getElementsByTagName('html')[0];//设置根元素字体htmlDom.style.fontSize= htmlWidth/20 + 'px';这种形式目前罕用于webapp上,次要是应用rem个性来灵便扭转字体大小,达到窗口大小扭转等比缩放元素。 拓展局部:目前在自适应这块像对于互联网电视,因为开发时候对图片尺寸是有严格要求,因而,集成时候只须要设置视口大小就能够对任何屏幕进行等比缩放。个别会在meta标签中间接设置开发时候基准的大小<meta name="page-view-size" content="1920*1080" />

February 7, 2021 · 1 min · jiezi

关于chrome:昨晚-Chrome-浏览器停用了-The-Great-Suspender-插件

Google 曾经显著地阻止了 Chrome 的 The Great Suspender 扩大程序,现有用户当初收到一条音讯,称其“因为蕴含恶意软件而被禁用”。 它也已从Chrome网上利用店中删除,指向它的所有链接当初都指向404页面。有些人放心失落标签,然而 Reddit 用户曾经找到了一种办法来复原它们(来自 XDA-Developers 的 Mishaal Rahman)。 Great Suspender 是一个十分有用的扩大,能使浏览器不会占用太多的内存。该工具会主动挂起一段时间未应用的标签,将其替换为空白的灰色屏幕。能够单击以从新加载回原来的地位。鉴于 Chrome 浏览器偏向于占用大量计算机内存,因而该扩大程序是一种使浏览器运行速度更快的简略办法,而实际上并没有强制敞开旧标签页。 如果您应用了扩大,并心愿失去您的标签,步骤是简略的,就是有点繁琐。如果选项卡是关上的,您能够转到它们并单击进入 URL 栏。会有很多这样的文本: chrome-extension://klbibkeccnjlkjkiokjodocebajanakg/suspended.html#ttl=%22Dawn%22%20Dario%20Marianelli%20(Pride%20%26%20Prejudice)%20Piano%20solo%20%26%20Tutorial%20-%20P.%20Barton%20-%20YouTube&pos=0&uri=https://www.youtube.com/watch?v=RJXGLl_sEDU下面是所在页面的地址,删除 uri 之前的所有内容并按回车键可使页面复原原样。 Reddit 用户 avatar_ENG 还发现,依然能够通过搜寻 Chrome 历史记录来找回这些标签。基本上与上述过程雷同:搜寻扩大程序的 ID klbibkeccnjlkjkiokjodocebajanakg,而后关上标签页并删除垃圾邮件。这可能是一个令人烦恼的过程,然而总比失去关上的任何工作好。 Google 和扩大程序的开发人员都没有立刻回应置评申请。 译自:https://www.theverge.com/2021/2/4/22266798/chrome-blocks-the-great-suspender-disabled-malware-tab-recovery原文链接:https://k8scat.com/posts/the-great-suspender-for-chrome-is-blocked/

February 5, 2021 · 1 min · jiezi

关于chrome:服务网格的最佳实践

简介: 服务网格是用于解决服务间通信的专用基础设施层。它负责通过蕴含古代云原生应用程序的简单服务拓扑来牢靠地传递申请。微服务倒退的这几年,新的技术和概念层出不穷,这些技术的引入实质上都是在围绕服务稳定性和业务开发效率晋升,最近两年服务网格越来越被宽广的微服务用户所认知。 在 Kubernetes 曾经成为云原生时代的操作系统的明天,如何更好的拥抱 Kubernetes 生态,实现业务疾速上云,享受云计算带来的能力,其中服务网格是一个必须要提的关键技术,然而在服务网格应用过程中咱们会碰到很多的问题,比方:如何让现有的利用迁徙到服务网格,如何反对多种语言、框架的互通和治理,如何应用可观测产品排查问题,接下来我将从如何接入服务网格、异构服务框架、语言的互通和可观测三个方面答复这个问题。 迁徙利用到服务网格中服务网格 服务网格是用于解决服务间通信的专用基础设施层,它负责通过蕴含古代云原生应用程序的简单服务拓扑来牢靠地传递申请。实际上,服务网格通常通过一组轻量级网络代理来实现,这些代理与利用程序代码一起部署,而不须要感知应用程序自身。 目前支流的服务网格开源软件是 Istio,其整体架构如下: 从图中能够看到服务网格与业务容器是在同一个 Pod 中的不同容器,带来的劣势有如下三点: 1.微服务治理与业务逻辑的解耦。服务网格把 SDK 中的大部分能力从利用中剥离进去,拆解为独立过程,以 Sidecar 的模式进行部署,服务网格通过将服务通信及相干管控性能从业务程序中拆散并下沉到基础设施层,使其和业务零碎齐全解耦,使开发人员更加专一于业务自身。 2.异构语言/框架的对立治理。随着新技术的倒退和人员更替,在同一家公司中往往会呈现不同语言、不同框架的利用和服务,为了可能对立管控这些服务,以往的做法是为每种语言、每种框架都开发一套残缺的 SDK,保护老本十分之高,而且给公司的中间件团队带来了很大的挑战,有了服务网格之后,通过将主体的服务治理能力下沉到基础设施,多语言的反对就轻松很多了。 3.服务网格岂但能够承当流量代理,对于业务共用的、通用的场景和需要都能够成为服务网格的一部分,这样能无效进步业务开发效率。 利用接入服务网格目前服务网格对 Kubernetes 反对最残缺,同时也反对了 VM 的利用接入,然而须要较多的配置,咱们举荐首先将 VM 上的服务容器化后在接入网格中,逐渐迁徙已有的利用,通过网关来买通服务网格中的利用和 VM 中没有接入服务网格的利用。 服务网格的接入首先是须要装置 Istiod,而后通过对 Namespace 打标来实现 Sidecar 的主动注入,能够选择性的对一些服务不进行 Sidecar 的注入,比方相似 MySQL、Redis 等中间件利用,次要是缩小 Envoy 带来的提早,在 EDAS 中能够针对每个利用进行打标,对须要退出服务网格的利用才进行 Sidecar 的注入。 异构微服务的互通、治理因为业务的倒退,基于业务产品的抉择,业务开发语言越来越多种多样,这些语言之间的互通成为大家关注的问题,目前常见的场景如 Java 语言和非 Java 语言的互通,互通中最重要的问题就是服务发现和通信协议的反对。 服务发现通常咱们在应用 Kubernetes 上部署服务如下,其中定义了 Kubernetes Service 用于服务间申请的域名: apiVersion: apps/v1kind: Deploymentmetadata: name: details-v1 labels: app: details version: v1spec: replicas: 1 selector: matchLabels: app: details version: v1 template: metadata: labels: app: details version: v1 spec: containers: - name: details image: docker.io/istio/examples-bookinfo-details-v1:1.16.2 imagePullPolicy: IfNotPresent ports: - containerPort: 9080apiVersion: v1kind: Servicemetadata: name: details labels: app: details service: detailsspec: ports: - port: 9080 name: http selector: app: detailsIstio 监听 Kubernetes Api Server,获取服务的 Service、Pod 等数据,通过 XDS 形式提供给 Envoy,Envoy 会通过获取的数据做负载平衡。 ...

February 5, 2021 · 2 min · jiezi

关于chrome:黑灰产攻击洪峰来袭企业如何守住自己的钱袋子

简介: 风控大考最佳实际 依据阿里云历史行业危险治理相干数据显示,未经危险管控的天然流量中,约三分之一比例属于疑似黑灰产的高风险行为;而在建设正当的风控指标监控体系并采取危险防控伎俩后,高风险用户比例降落至3%以内,降落比率超过90%。 无效的危险防控计划是保障各类营销、促活拉新等流动成果的必要伎俩。 随着春节邻近,局部互联网行业迎来业务顶峰,企业为了抢夺用户流量将投入大量获客、营销资源,但同时也将面临风控大考。 因为各行业、企业的业务场景及逻辑多种多样,黑灰产须要借助工具能力实现团伙作案。阿里云平安团队梳理了近年来支流的被黑灰产应用的作案工具,并剖析其作案原理及攻打手法,为企业晋升防控精准度和防控效率提供参考。 云 手 机云手机即一台运行在云端服务器的虚构手机,具备云计算赋予的超大规模、弹性扩容、成本低等劣势,常常被用于挪动办公、AIoT、工业互联网等场景。然而,这些翻新的技术工具也被黑灰产瞄上,用在了攻打套利方面。 传统危险治理次要通过设施指纹等技术手段进行风控治理,因而黑灰产须要购买多台真机能力实现作案。但借助云手机,黑灰产只须要一个云手机厂商账号就能够同时开启大量新机批量套利,作案老本大大降低。 此外,黑灰产能够将云手机虚构成各类实体手机的品牌型号作案,企业风控人员如果对云手机没有足够的认知,很难将舞弊类的云手机设施与失常云手机用户辨别开,危险辨认挑战减少。 常见套利场景 薅羊毛:黑灰产利用云手机实现低成本设施群控,再应用脚本工具进行批量注册、养号,歹意攻打或者寻找企业营销流动破绽,囤积平台权利,进行倒卖套利。游戏打金:黑灰产注册大量游戏账号,借助云手机装置舞弊利用来养号,以取得高价值游戏配备,而后通过特定交易渠道卖出,实现套利。攻防原理 黑灰产能够通过云手机实现设施群控,从而实现大量虚伪账号的注册、登录及沉闷养号,而后依据不同行业业务个性实现套利,具备批量、自动化操作等危险特色。 针对这一状况,企业能够基于业务场景、危险画像标签搭建正当的业务指标监控体系,从而及时感知危险异动。比方:针对监控指标进行时序剖析、操作行为聚类分析、团伙发现剖析等,无效发现黑灰产危险行为。 改 机 工 具改机,即把设施固有的硬件信息、软件信息、传感器信息,如:IMEI、IMSI、零碎版本、内核版本、GPS、陀螺仪等,批改成用户自定义的信息,以此来骗过大多数APP的信息采集性能。 黑灰产团伙利用改机工具可能产生新的设施指纹,以此来绕过单设施无奈注册多账号的限度,实现批量账号的注册、登录、养号,为后续攻打套利提供物料。 常见套利场景 薅羊毛:比方黑灰产能够利用改机工具批改设施信息,假装成为“新用户”,用来规避平台对有过“案底”的黑设施检测,或是刷取一些对支付账号资质有要求的高价值权利,进行套利。营销推广舞弊:黑灰产通过改机工具一直刷新设施指纹,绕过平台风控规定,批量注册小号,并进行广告点击、刷单、刷赞等舞弊操作,耗费商家营销推广资源。攻防原理 互联网营销流动中,大多数企业会通过限度设施参加流动次数来避免黑灰产批量薅羊毛;在遭逢攻打后,则通过建设设施“黑名单”来避免危险行为再次发生。而黑灰产通过改机工具,能够绕过上述限度,进行套利。 · 改机工具无奈做到和官网手机完全一致,因而通过建设支流机型设施参数库进行设施参数比对,便能发现黑灰产作案的蛛丝马迹; · 市面上的改机工具个别是基于特定框架实现的,如:Xposed;因而通过检测Xposed、注入模块、系统文件等办法,能及时发现设施是否存在改机行为; · 通过对设施参数进行合法性校验也能够在肯定水平上发现改机行为。 改机工具界面 应 用 多 开因为零碎限度,同一软件在一个手机上只能装置一个。“利用多开”就是冲破这类零碎限度,实现在一部手机上同一利用装置多个,从而实现多账号自在切换 黑灰产不仅能够利用“利用多开”养号,更重大的是多开工具能截获指标APP的网络流量,从而实现监听网络包、截取登陆账号密码、窥探IM软件聊天记录,导致失常用户信息被第三方多开利用滥用于黑灰产流动。 利用多开工具实现同一手机装置多个雷同利用 常见套利场景 “杀猪盘”社交利用多账号操作:“杀猪盘”指欺骗分子利用网络交友,诱导受害人投资赌博的一种电信欺骗形式。黑灰产团伙应用多开软件等工具能够做到广撒网,实现1对N的音讯发送,进步作案效率。虚伪推广刷量:黑灰产借助多开工具刷量,耗费用于拉新或促活流动中的投放资源,影响流动转化成果,给企业带来资损。歹意引流:黑灰产通过批量利用分身,实现批量登录、操控账户,大量发送“牛皮藓”音讯进行歹意引流。攻防原理 目前市面上被黑灰产利用的多开软件多种多样,其中手机版虚拟机是行业中较新的一种舞弊计划。 手机版虚拟机多开计划借鉴了qemu的实现原理,应用原生零碎的Linux内核,在本人的APP外部搭建了一个新零碎的rootfs。此类工具是近期最新呈现的挪动端虚拟机,可在Android手机上模仿进去另外一个独立的Android零碎,并且自带各种舞弊插件。 歹意多开利用常见于同设施操作,因而通过终端危险检测及服务端基于设施、操作环境、团伙聚类等形式可及时发现歹意多开行为。 虚 拟 定 位虚构定位即在获取到高权限的手机上从底层批改零碎GPS采集的地位信息,坑骗手机APP获取歹意假装的假GPS数据。 常见攻打场景 网约车刷单:针对网约车业务场景,利用虚构定位工具模仿行驶,实现刷单,套取平台垫付金及处分。 社交App虚构定位欺骗:批改定位后以虚拟地址在社交利用上进行色情类欺骗。 商家信息爬取:批改定位后主动爬取左近商家的商品、价格等信息,售卖得利,常见于歹意市场竞争。攻防原理 拦挡API,接口获取设施地位信息 应用规定文件替换地位数据 绕开系统对舞弊插件的检测,达到插件隐身的目标。 把握了虚构定位工具的实现原理,能够联合业务场景进行更有针对性地危险检测及防护。 阿里云平安专家支招业务危险防控1. 欠缺业务设计,进步作案门槛 针对有可能存在资损的流动与业务流程: 适当晋升用户参加门槛,如限定同设施、手机号参加流动的最高次数,以避免黑灰产“薅羊毛”;减少核销规定,如:对现金券类的高价值权利的兑现应用进行账户资质、行为达标等多条件强校验。2. 被动监测危险异动,分层治理 通过被动监测流动营销资源核销比例及速率,联合账户行为、设施危险状况,被动进行实时与近实时的异动监控。对于捕捉到的异样事件进行量化评估,依据对业务的影响水平做不同解决,对具备潜在资损的流动权利进行正当的分层挽回与止损。 3. 与业余风控团队单干 目前市面上的黑灰产作案工具、作案手法层出不穷。企业自建风控团队通常耗时会超过半年,而大多数业务危险问题从产生到暴发的工夫都很短,几小时就足以造成巨额损失。因而与业余的风控团队建设单干能够无效补救企业本身的能力短板,同时节约自研老本。 值得一提的是,业务风控是高度依赖实战经验的畛域。阿里云业务风控团队在阿里巴巴团体本身十余年的危险管控过程中积攒了丰盛的最佳实际,联合大数据、流式计算、机器学习算法等翻新技术,能够为企业提全链路跨危险场景的“端+云”的联防风控计划。 ...

February 5, 2021 · 1 min · jiezi

关于chrome:mac-chrome-书签误删找回

mac书签误删找回 找到书签文件浏览器输出 chrome://version 按下回车键 用户数据保留门路 /Users/whw/Library/Application Support/Google/Chrome/Profile 1#进入书签所在目录cd /Users/whw/Library/Application\ Support/Google/Chrome/Profile\ 1#复原误删之前的书签cp Bookmarks.bak.bak Bookmarks 重启chrome即可

February 4, 2021 · 1 min · jiezi

关于chrome:前端面试每日-31-第655天

明天的知识点 (2021.01.30) —— 第655天 (我也要出题)[html] 页面上如何显示特殊字符?[css] 用css暗藏input的光标[js] js的作用域有哪些?[软技能] 说说你对前端图表利用的了解《论语》,曾子曰:“吾日三省吾身”(我每天屡次检查本人)。前端面试每日3+1题,以面试题来驱动学习,每天提高一点!让致力成为一种习惯,让奋斗成为一种享受!置信 保持 的力量!!!欢送在 Issues 和敌人们一起探讨学习! 我的项目地址:前端面试每日3+1【举荐】欢送跟 jsliang 一起折腾前端,零碎整顿前端常识,目前正在折腾 LeetCode,打算买通算法与数据结构的任督二脉。GitHub 地址 微信公众号欢送大家前来探讨,如果感觉对你的学习有肯定的帮忙,欢送点个Star, 同时欢送微信扫码关注 前端剑解 公众号,并退出 “前端学习每日3+1” 微信群互相交换(点击公众号的菜单:交换)。 学习不打烊,充电加油只为遇到更好的本人,365天无节假日,每天早上5点纯手工公布面试题(死磕本人,愉悦大家)。心愿大家在这虚夸的前端圈里,放弃沉着,保持每天花20分钟来学习与思考。在这变幻无穷,类库层出不穷的前端,倡议大家不要等到找工作时,才狂刷题,提倡每日学习!(不忘初心,html、css、javascript才是基石!)欢送大家到Issues交换,激励PR,感激Star,大家有啥好的倡议能够加我微信一起交换探讨!心愿大家每日去学习与思考,这才达到来这里的目标!!!(不要为了谁而来,要为本人而来!)交换探讨欢送大家前来探讨,如果感觉对你的学习有肯定的帮忙,欢送点个[Star]

January 30, 2021 · 1 min · jiezi

关于chrome:对话阿里云李飞飞下一代企业级数据库6大技术方向

简介: 对话李飞飞,不仅仅是一次简略的采访,对老鱼来说,也是一种播种,因为,在数据库畛域李飞飞领有敏锐的触角,对数据库发展趋势有着独到的见解和洞察。题图:DTCC 2020大会专访合影(左:老鱼 右:李飞飞) 在2020年12月完结的DTCC2020,“百库争鸣”或者是参会者最大的感触。据不齐全统计,目前有名有姓的国产数据库产品多达200种。 百花齐放,百家争鸣,这正是用户所须要的。数据库被国家列为“卡脖子”的35项关键技术之一。只有对数据库根底钻研越器重,参加的企业越多,关注的人越多,才有可能诞生更好的数据库软件。 下一个10年,数据库发展趋势是什么?用户须要什么样的数据库?这可能是很多从业者都想晓得的问题,而这些问题,在DTCC2020大会上就有答案。 大会第一天,阿里巴巴团体副总裁,阿里云智能数据库产品事业部负责人李飞飞就分享了他对数据库畛域的察看,并指出了下一代企业级数据库的6个关键技术方向。 家喻户晓,Gartner最新颁布的2020 年度寰球云数据库魔力象限评估后果,国内有3家厂商进入,其中阿里云更是挺进了第一营垒——领导者(LEADERS)象限。这意味着在云数据库这条赛道上,中国数据库并没有落后于人,并且真正走进世界一流。 很多人或者没留意到,往年Gartner将OPDBMS(Operational Database Management Systems)和DMSA(Data Management Solutions for Analytics)两个本是离开畛域合二为一,成为CDBMS(Cloud Database Management Systems)。 为什么Gartner要这样做?因为Gartner认为“There is Only One Cloud Database DBMS Market”。这不仅意味着CDBMS魔力象限竞争更为强烈,含金量更高,也意味着一种趋势,数据库和数据仓库是能够交融的。 因而,阿里云对下一代企业级数据库关键技术的判断还是极具参考价值的。 但对于6种关键技术,外界其实还存在一些不同的声音。比方,有一种声音认为,HTAP只是一种场景需要,并非一种趋势。分布式是将来吗?软硬件一体化是不是又回到了被锁定的老路? 为此,老鱼在会后特意专访李飞飞,就这些问题开展探讨。 以下为本次专访对话内容精选: 老鱼:在您看来,过来的10年,中国数据库技术倒退出现怎么的趋势?下一个10年会朝怎么的方向倒退? 李飞飞:过来十年,数据库畛域最大的趋势,我感觉是从传统数据库架构向云原生架构演进的趋势。 云厂商的崛起,是过来十年十分典型的特色。没有人会想到,忽然有一天,亚马逊也开始做数据库了,并悄无声息的就已达到了寰球数据库当先地位。我认为,这跟云计算新赛道带来的时机是密不可分的。 云计算带来的云原生技术体系催生了云原生数据库和云原生数据仓库。像AWS Aurora,AWS Redshift, Snowflake, 阿里云PolarDB、AnalyticDB(ADB)。我认为,都是新赛道带来的全新倒退时机,这是一个十分典型且有着时代代表性的趋势,向云原生演进。 另外一个大趋势,是分布式技术的深度倒退。过来十年,分布式技术从一个比拟高级的状态倒退到明天,有了明天的分布式数据库和分布式数据仓库。 接下来的十年,有哪些趋势? 第一、云原生和分布式会产生深度交融,架构上无缝交融,提供更好的弹性、高可用能力。 第二、智能化技术深度交融,在数据库中,如何用AI和相干技术,去做到智能化的运维管控,比方索引举荐,MySQL治理、异样检测等。 第三、数据库大数据一体化,包含HTAP以及离在线一体化,在过来的十几年里,数据库畛域和大数据畛域是离开的,一个做离线,一个做在线,相安无事。但从利用角度或客户视角看,越来越多的客户和利用须要最好是一套零碎来解决数据从生产、解决、存储、生产全链路的过程,客户越来越心愿缩小数据挪动和存储老本,防止天天做数据同步。如果可能实现离在线一体化或可能实现HTAP事务剖析一体化或离线计算在线查问一体化,那这些问题都能够迎刃而解。这也是我认为,下个十年十分要害的趋势。这也是为什么Gartner将OPDBMS(Operational Database Management Systems)和DMSA(Data Management Solutions for Analytics)两个本是离开畛域合二为一背地的外围逻辑。 第四、多模,除了结构化数据,怎么去解决文本、图片等非结构化和半结构化数据?用数据库办法去交融解决这些数据。 第五、软硬件一体化,肯定要关注硬件倒退,比方:NVM、高速网络等新硬件对数据库系统设计带来的冲击。 第六、平安可信,这是个永恒的话题。不是最新趋势,但会一直演进。如何联合区块链技术在数据库系统里提供不可篡改性,如何将加密技术做到数据库里对数据进行全程加密爱护。 老鱼:对于HTAP还是颇有些争议。有观点认为,HTAP只是一种细分应用场景,还谈不上不是将来数据库的趋势,并且不倡议把OLTP和OLAP业务齐全混合,认为在典型的OLTP解决场景就应用面向OLTP设计的数据库,否则,既达不到OLAP的扩展性,又无奈满足OLTP的实时、高性能等要求。您怎么看? 李飞飞:中国有句古话,鱼和熊掌不可兼得。如果,明天有人通知用户说“我明天做了个HTAP数据库能够替换传统的OLTP数据库,也能够替换传统的OLAP数据仓库,传统的OLTP、OLAP零碎都没有用了”,那是不可能的。 如果用户就是在线交易场景、高并发、读写抵触十分高,这种状况下还要做OLAP,做多表聚合查问,是非常复杂的。此种状况下,和高并发事务放在一起,肯定会有挑战。 那为什么还要讲HTAP,我认为并不是要彻底取代传统OLTP或彻底取代传统OLAP数据库,HTAP有本人的市场。一些在线事务、在线交易的场景下,如果做一些不太简单的剖析,或者做简单剖析但隔离级别要求没那么高,对实时性要求也不那么高,在这种场景下,能不能做到既做OLTP又做OLAP?那是有可能的。 比方,在咱们事务处理里,都做三正本,三正本里能够做行列转换,两个正本能够是行存,第三个正本是列存,去读列存正本,并保障高隔离机制高实时可见要求,在这种场景下是没问题的。但如果做非常复杂,时效性要求十分高的剖析计算,还是要专门的OLAP零碎。 另外,将离线和在线一体化,既能做在线交互式剖析也能做离线ETL是刚需。这个过程中,既然要做实时增、删、改、查又要做交互式剖析和简单离线计算(然而前提是在肯定的隔离级别以下,比方RC),肯定会产生HTAP场景,但这个HTAP和现实中的HTAP既能反对高隔离级别、高并发还能做简单剖析是两个概念。 我感觉,将来的场景肯定是有简单剖析计算场景、数据库大数据一体化场景,不论从那种角度, OLAP反对肯定级别的OLTP, OLTP做得十分好还能兼顾肯定的OLAP,这种场景是存在的。 老鱼:这几年,分布式数据库十分火,很多企业都在试水,有胜利的,也有失败的,有种说法,数据量不上肯定规模,没有超高峰值,没有高并发的场景就没必要用分布式数据库,因为,很可能不能取得什么显著劣势。您怎么看? 李飞飞:在明天的演讲中,我旗帜鲜明的提到,不能为了分布式而分布式。明天分布式很火,有泛滥起因。在美国市场,分布式OLTP数据库商业化胜利的案例并不多。以Oracle为例,并没有将分布式作为最重要的主攻方向。 ...

January 28, 2021 · 1 min · jiezi

关于chrome:Flink-助力美团数仓增量生产

简介: 本文由美团研究员、实时计算负责人鞠大升分享,次要介绍 Flink 助力美团数仓增量生产的利用实际。内容包含:1、数仓增量生产;2、流式数据集成;3、流式数据处理;4、流式 OLAP 利用;5、将来布局。一、数仓增量生产1.美团数仓架构 先介绍一下美团数仓的架构以及增量生产。如下图所示,这是美团数仓的简略架构,我把它叫做三横四纵。所谓三横,第一是贯通全链路的元数据以及血统,贯通数据集成、数据处理、数据生产、以及数据利用的全过程链路。另外一块贯通全链路的是数据安全,包含受限域的认证零碎、权限零碎、整体的审计零碎。依据数据的流向,咱们把数据处理的过程分为数据集成、数据处理、数据生产、以及数据利用这 4 个阶段。 在数据集成阶段,咱们对于公司外部的,比如说用户行为数据、日志数据、DB 数据、还有文件数据,都有相应的集成的零碎把数据对立到咱们的数据处理的存储中,比如说 Kafka 中。在数据处理阶段,分为流式解决链路、批处理链路以及基于这套链路的数仓工作平台(万象平台)。生产进去的数据,通过 Datalink 导入到生产的存储中,最终通过利用以不同的模式出现进去。 咱们目前在 Flink 下面利用比拟宽泛的中央,包含从 Kafka 把数据导到 Hive,包含实时的解决,数据导出的过程。明天的分享就集中在这些方面。 2.美团 Flink 利用详情 美团的 Flink 目前大略有 6000 台左右的物理机,撑持了 3 万左右的作业。咱们生产的 Topic 数在 5 万左右,每天的顶峰流量在 1.8 亿条每秒这样的程度上。 3.美团 Flink 利用场景 美团 Flink 次要利用的场景包含四大块。 第一,实时数仓、经营剖析、经营剖析、实时营销。第二,举荐、搜寻。第三,风控、系统监控。第四,平安审计。 4.实时数仓 vs 数仓增量生产 接下来我要引入增量生产的概念。离线数仓关注的三块需要,第一个就是时效性。第二个就是品质,产出的数据的品质。第三个就是老本。 对于时效性,有两个更深层次的含意,第一个叫做实时,第二个叫准时。并不是所有的业务需要都是实时的,很多时候咱们的需要是准时。比方做经营剖析,每天拿到相应的昨天的经营数据状况即可。实时数仓更多的是解决实时方面的需要。然而在准时这一块,作为一个企业,更心愿在准时跟老本之间做一个衡量。所以,我把数仓的增量生产定义为对离线数仓的一个对于准时跟老本的衡量。另外,数仓增量生产解决比拟好的一个方面是品质,问题可能及时发现。 5.数仓增量生产的劣势 数仓增量生产的劣势有两点。 可能及时发现数据品质问题,防止 T+1 修复数据。充分利用资源,提前数据产出工夫。如下图所示,咱们冀望做的实际上是第二幅图。咱们冀望把离线的生产占用的资源升高,但同时心愿它的产出工夫可能提前一步。 二、流式数据集成1.数据集成 V1.0 咱们来看一下流式数据集成的第一代。当数据量十分小以及库非常少的时候,间接做一个批的传输零碎。在每天凌晨的时候把相应的 DB 数据全副 load 一遍,导到数仓外面。这个架构劣势是非常简单,易于保护,然而它的毛病也非常明显,对于一些大的 DB 或者大的数据,load 数据的工夫可能须要 2~3 个小时,十分影响离线数仓的产出工夫。 ...

January 28, 2021 · 2 min · jiezi

关于chrome:记一次前端chrome插件基础实战分享会建议收藏下篇

承接上文十. 鼠标右键菜单须要先在权限外面加上菜单的权限manifest.json "permissions": ["contextMenus"],.具体的增加菜单的代码, 咱们放在background.js文件外面 chrome.contextMenus.create({ title: "敢不敢点击我", onclick: function(){alert('点击了人家');} }); 这里点击后就调用咱们定义的点击办法了 第二种形式: 咱们把菜单做成选项, 比方三种模式让用户选一种 chrome.contextMenus.create({ title: "选项1", "type": "radio", onclick: function(){alert('应用1');}});chrome.contextMenus.create({ title: "选项2", "type": "radio", onclick: function(){alert('应用2');}});chrome.contextMenus.create({ title: "选项3", "type": "radio", onclick: function(){alert('应用3');}}); 当然了, 多选也是有的 chrome.contextMenus.create({ title: "选项1", "type": "checkbox", onclick: function(){alert('应用1');}});chrome.contextMenus.create({ title: "选项2", "type": "checkbox", onclick: function(){alert('应用2');}});chrome.contextMenus.create({ title: "选项3", "type": "checkbox", onclick: function(){alert('应用3');}}); 右键菜单的第二大类只有选中某些内容了才展现的菜单 chrome.contextMenus.create({ title: '选中了:%s', // %s示意选中的文字 contexts: ['selection'], // 只有入选中文字时才会呈现此右键菜单 onclick: function(params) { alert('查问某个货色') } });第一种与第二种菜单同时creat, 显示时只显示对应的一种状况 ...

January 27, 2021 · 2 min · jiezi

关于chrome:记一次前端chrome插件基础实战分享会建议收藏上篇

记一次前端"chrome扩大"简略易懂的实战分享会(上)记录了我在组内的技术分享, 有同样需要的同学能够参考一下分享全程下来工夫大概67分钟 一. 为啥要学这个身为前端工程师,浏览器是咱们的主战场, 而咱们岂但要会应用浏览器, 还要利用浏览器, 外围是学习浏览器的一些编程思维,让咱们更加厉害。当然了看的见的益处就是咱们能够利用chrome的扩大技术做一些好玩的小工具陶冶情操。本文没有大型的概念, 目标是让你最轻松, 最疾速的学会开发插件. 本文次要讲述干货次要常识,小知识点有没笼罩到的请查阅官网,如果是一个初学者了解完本篇文章也具备了开发的能力。二. 什么样的'文件'算chrome扩大没学习相干常识之前,认为须要是某些特定后缀的文件才是扩大程序相似我之前分享过的vscode插件vscode插件开发, 而chrome的扩大只须要一个json入口文件即可, 当然如果你要发到chrome商店的话还是须要打包一下的。而这次要的入口文件就是manifest.json名字必须叫这个。如下内容: { "manifest_version": 2, // 应用的哪个版本的规定开发扩大 "name": "谷歌扩大", // 这个是要显示在插件页面的 "description": "用于分享常识", // 插件的介绍 "version": "1.0", // 这个版本号会显示在插件上面, 所以不是轻易填写的 "browser_action": { "default_icon": "images/qian.png" // 默认显示的图片 }}"manifest_version" 应用1的话会报错, 所以当初都用2了. 为寄存相干图片, 咱们建设图片文件夹 是不是不太置信, 这就实现了一个最最根本的'插件'关上开发者模式 在管制页面导入这个插件 导入咱们开发的相干文件夹, 也就是manifest.json寄存的文件夹 插件曾经失效了, 咱们把他放到里面便于应用, 如图步骤: 当初咱们就取得了属于咱们本人的谷歌插件 三. 更新插件这里更新单拿出来说, 是为了不便汇总, 看到前面大家也能够来这里查, 当然上面也会反复说相干操作 更新插件, 请点击2, 点击1也能够做到更新, 然而他是更新全副, 哪怕只有一个扩大他也会联网申请更新, 节约半分钟的工夫, 只有在电脑断网的状况下才会立即更新本地插件, 所以你懂他的更新机制了吧, 所以开发时候举荐选用2的办法更新插件.devtools: 须要f12敞开控制台, 再f12关上控制台才能够更新, 并且不能够是chrome://extensions/, 须要抉择一个无效的网址.background: 每次更新插件或者重开浏览器才刷新, 敞开某个页面是不会刷新的.popup: 每次点击都是从新加载popup程序四. background 的概念和玩法咱们插件跑在用户的浏览器上, 那么它当然也会存在一个背地运行的后盾控制系统, 要不然怎么操控这个插件?而这个控制系统就是background, 咱们在manifest.json外面加上一条 ...

January 26, 2021 · 2 min · jiezi

关于chrome:阿里云拨测主动探测Web应用质量助力提升用户体验

简介: 阿里云拨测是一种针对互联网利用(Web页面、网络链路等)进行利用性能和用户体验监测的服务,无需嵌码即可为云上用户提供开箱即用的企业级被动拨测式利用监测解决方案。随着中国数字化经济的蓬勃发展,越来越多的企业大力发展线上业务。例如,某传媒机构开设新闻资讯网站,并在网站经营保护上每年收入超过500万元;某零售商开设电子商务服务网站,每年在网站经营保护上的支出费用超过200万元…… 那么,对于企业来说,怎么事后评估本身Web利用是否已达到目标服务质量和用户体验?如何精准定位终端用户拜访Web利用过程中遇到的故障及其根因?怎么无效掂量本身与竞品的性能和体验差距? 计划:真机拨测,事后感知Web利用品质与用户体验阿里云拨测是一种针对互联网利用(Web页面、网络链路等)进行利用性能和用户体验监测的服务,无需嵌码即可为云上用户提供开箱即用的企业级被动拨测式利用监测解决方案。 场景1:事后感知终端用户的应用体验场景某电子商务服务网站月活用户数超过100万,用户群体次要散布在全国三、四、五线城市,每年在网站经营保护上的支出费用超过200万元。商品信息更新较频繁,为更高效的解决更新后收到各地用户投诉“商品图片加载不进去”、“页面关上迟缓”等问题,可应用云拨测,选取全国不同城市运营商的监测点,设定浏览和网络工作,实时获取第一线的实在用户拜访体验数据,精准定位呈现问题的页面元素,帮忙技术团队及时修复问题,同时用户投诉率降落了80%左右! 场景2:精准定位Web利用故障根因某新闻资讯网站日活用户数超过300万,用户遍布全国,每年在网站经营保护上的支出费用超过500万元。为更高效的解决其余各地用户投诉“网站不能失常拜访”、“新闻关上迟缓”,但本地验证时却能够失常拜访等问题,可应用云拨测,在不同地区运营商条件下,比照该网站的整体性能、可用性、页面渲染用时、时延等性能指标,把握全国不同城市运营商的用户拜访网站时的真实性能与用户体验数据,为制订网站经营保护策略提供无力的数据撑持,同时用户投诉率降落了85%左右! 场景3:时刻把握竞品性能与体验差别某大型线上生存服务机构网站日活用户数超过1000万,用户覆盖全国各省市,每年在网站经营保护上的支出费用数千万元,行业竞争强烈,为更高效的解决用户常常因为“拜访网站期待过长”等用户体验问题转而选用其余厂商的服务等问题,可应用云拨测,以终端用户视角对本身利用和竞品利用进行比照,从地区、运营商、工夫趋势、问题占比等多个维度组合分析,时刻把握竞品性能与体验差别,一直晋升本身竞争力,同时用户的留存率大幅回升! 劣势:深度数据挖掘,精准定位Web利用问题云拨测依靠笼罩寰球500+城市的主动式监测网络(蕴含IDC节点和实在网民PC节点),以海量工作智能调度技术、高并发大数据实时处理技术为外围,在监测精度上实现页面元素级、网络申请级、网络链路级的问题定位,在用户应用上实现多频率工作的并发,在数据分析上实现多图表、多维度的组合分析。 精确精密的问题定位目前,云拨测反对针对Web页面的浏览拨测和针对网络链路的网络拨测。浏览拨测工作反对发现页面元素级谬误,并可将问题起因精准定位至单次网络申请过程,能够无效晋升页面性能和用户体验。网络拨测工作反对DNS、Ping、Tracert,能够完满笼罩网络链路品质监控场景。 丰盛的多维度数据分析模型云拨测反对从地区、城市、运营商等多个维度组合分析,并可下钻剖析单样本详情,联合丰盛的指标体系和直观的柱状图、条形图、折线图、散点图等在线图表,疾速定位问题受影响的范畴及其根本原因。 弱小的竞品比照能力借助云拨测无需批改利用代码或嵌码的技术能力,既能够对本身利用进行性能监测,也能够对竞品利用进行比照监测,时刻把握竞品差别,做出更具劣势的竞争策略。 事后感知用户体验程度利用云拨测的主动式拨测模式,能够在终端用户之前清晰理解指标利用在寰球终端用户侧的网络、浏览等数字性能体验,提前定位、解决每一次用户体验的不良问题。 成果:数据可视化与外围指标体系 云拨测平台反对从地区、城市、运营商等多个维度组合分析,疾速定位问题及受影响的范畴,领有齐备的网络和浏览服务质量指标体系。 浏览服务质量次要指标体系整体性能算法:某段时间内从页面开始浏览到最初一包数据接管实现之间的工夫距离的平均值。价值:反映终端用户从触发“加载网页”到真正页面渲染实现的期待时长,体现浏览服务的用户体验。 100KB耗时算法:均匀加载100KB内容所需耗时。价值:更加迷信公正的展示不同页面加载耗时。 首屏用时算法:从输出URL开始到页面已渲染区域高度大于等于指定高度的时间差,默认是600像素高。价值:从用户体验角度掂量页面渲染成果。 可用性算法:执行监测工作的客户端对指标拜访的成功率。价值:反映对可用水平的总体评估。 下载量算法:下载量=无效散点的下载字节总量/无效的散点个数。价值:反映下载字节数的性能。 网络服务质量次要指标体系时延算法:一个报文或分组从一个网络的一端传送到另一端所须要的工夫。价值:反映路由的真实情况。 丢包率算法:丢包率=失落数据包量/所传数据包总数*100%价值:反映以后网络环境好坏的重要评估规范。 DNS查问用时算法:将域名解析成IP地址须要的工夫。价值:反映域名解析成IP地址的性能。 解析错误率算法:解析域名的过程中,呈现谬误次数的占比。解析错误率=解析谬误数/解析域名总数*100%价值:反映域名解析谬误的性能。 云拨测在监测精度上实现页面元素级、网络申请级、网络链路级的问题定位,在用户应用上实现多频率工作的并发,在数据分析上实现多图表、多维度的组合分析。云拨测利用遍布寰球的监控网络,在生产环境下,被动模仿实在用户并对利用进行探测,不影响利用的失常运行,可实现采样样本数据收集,获取用户的体验数据、网络数据及竞品和行业数据,以实在终端用户应用场景为视角,对指标利用进行性能治理和网络性能监控,透视防火墙外的各环节性能,先于最终用户开掘故障隐患,助力云上用户晋升本身利用产品的用户体验。Web利用呈现品质问题时,云拨测能够迅速定位指标利用性能问题的受影响范畴及其根本原因,从而精准解决IT问题,晋升服务质量。 作者:中间件小哥 本文为阿里云原创内容,未经容许不得转载

January 26, 2021 · 1 min · jiezi

关于chrome:核桃编程前端可观测性建设之路

简介: 在3年工夫内,技术团队至多对整体零碎架构进行了6次以上的重大重构,波及微服务化、容器化、分布式数据库等重要的技术,并尝试通过Serverless技术晋升零碎的弹性伸缩能力。依据《中国少儿编程行业钻研报告》及《2017-2023 年中国少儿编程市场剖析预测钻研报告》预测得出,少儿编程无望在3-5年内,达到少儿英语市场规模的一半,即500亿左右,发展前景广大。 在信息化时代的明天,人工智能给人们带来了巨大变化,新时代的家长处于互联网时代,与上一代的家长思维产生较大的变动,可能重视孩子的素质教育,重视造就孩子人工智能方向的能力。少儿编程教育就是在这样的背景下疾速倒退起来。 核桃编程是少儿编程教育行业的领导者,致力于以科技伎俩促成编程教育,通过人工智能、自适应学习等先进技术和迷信的教育办法,启发中国孩子的学习能力。自2017年8月成立以来,核桃编程的业务量飞速发展,仅仅3年工夫付费学员人数就冲破了200万,并实现了单月营收过亿。 随着核桃编程业务的快速增长,外围利用的零碎规模和零碎复杂度也在经验天翻地覆的变动。核桃技术团队一直通过新兴的技术手段保护整套零碎架构的技术先进性。在3年工夫里,技术团队至多对整体零碎架构进行了6次以上的重大重构,波及微服务化、容器化、分布式数据库等重要的技术,并尝试通过Serverless技术晋升零碎的弹性伸缩能力。在疫情期间,当零碎负荷出现数倍突增的状况下,核桃编程的零碎架构仍然禁受住了考验。 随着零碎架构从简略变得复杂,有一个在互联网畛域老大难的问题也逐渐在核桃编程中体现进去:如何晋升分布式系统的可观测性?在线上编程教学场景外面,用户一个简略的操作,就有可能波及到前后端系统的屡次交互,以及多个服务端微服务利用之间的互相调用,甚至还会受到第三方服务接口的影响。任何一个环节呈现故障或者性能瓶颈,都会导致用户体验的断崖式上涨,而用户体验又是决定品牌形象的外围因素,所以对于核桃技术团队而言,保障优良的用户体验须要在零碎可观测性建设上做到这几个方面: 全面而且实时的理解零碎每一个对外接口的性能品质。通过数据把握最终用户与零碎交互时感触到的零碎衰弱水平。当零碎衰弱水平存在问题时,技术团队能第一工夫发现问题,并及时处理。解决问题时,能迅速定位到零碎瓶颈和故障源。任何一个技术团队要想围绕着这几个方面,从零开始建设分布式可观测体系,都是一项十分艰巨的工作,好在业界对于分布式可观测性的建设,曾经有了不少成熟的方法论以及开源我的项目能够参考。 业界宽泛认可的可观测性(observability)蕴含三个外围因素:Logging(离散的日志信息)、Metrics(聚合的指标)、Distributed Tracing(分布式追踪)。围绕这三个外围因素,有不少开源我的项目能够进行抉择,帮忙开发者疾速建设分布式可观测体系。 通过引入Skywalking,Prometheus等开源技术,核桃技术团队建设了残缺的分布式可观测体系,可能对服务端简单的微服务利用实现全链路追踪,并通过对立的日志服务体系收集剖析业务日志。这样的致力对于零碎稳定性以及用户体验的晋升是空谷传声的:当零碎服务端的任何一个环节呈现故障或性能瓶颈的时候,技术团队都能第一工夫失去告诉,并疾速定位问题,进行针对性解决。 绝对于成熟的服务端监控技术,整个业界在客户端监控畛域的技术计划始终比拟欠缺。在互联网上,海量的用户应用不同厂家、不同操作系统、不同屏幕分辨率的终端设备,散布在不同的地区,又通过不同的网络运营商进行接入,甚至存在简单的第三方依赖,包含CDN、第三方统计脚本、页面嵌套等方面。当用户体验遇到问题的时候,如果仅仅领有服务端监控伎俩,很难第一工夫确认问题的本源到底在于前端还是后端。即使可能排除服务端的问题,前端用户体验也受到页面渲染、JavaScript执行、网络品质、第三方接口服务质量等方面的影响,为进一步排查问题留下了十分多的挑战。 一个简略的思路是通过前端JavaScript做自定义的埋点,将最终用户的各种行为实时上报给服务端进行统计,以第一工夫理解到用户体验。这个思路自身是正当的,但业务埋点、数据采集、聚合剖析、视图展示等层面都有十分多的工作须要做,是一个盛大的工程。绝大多数技术团队而言,投入如此多的精力来建设这样一套前端监控计划都是不事实的。 建设前端可观测体系,最好的捷径是参考互联网畛域头部企业的案例,抉择云计算厂商提供的残缺计划。阿里巴巴多年实战积攒了一套全团体对立的前端监控计划,并凋谢给各个事业部接入。对于以HTML页面模式出现的前端利用,不论是PC端/挪动端网站,嵌入到挪动端App的HTML5页面,都能够通过无侵入的形式接入到这套前端监控计划中。 这套监控计划也同时通过阿里云对外输入,成为阿里云可观测性整体计划的重要组成部分,服务于宽广的内部用户。 在客户端监控畛域,包含ARMS前端监控和APP监控两个产品,其中ARMS前端监控专一于Web端体验数据监控,从页面关上速度、页面稳定性和内部服务调用成功率这三个方面监测Web页面的衰弱度,帮忙使用者升高页面加载工夫、缩小JS谬误,无效晋升用户体验。 这套计划正好能补齐核桃编程在客户端监控畛域的能力缺失,所以核桃技术团队尝试在一些业务线接入阿里云ARMS前端监控。很快,他们就感触到了这套计划对于晋升用户体验所带来的价值。 ARMS前端监控计划之所以能被核桃编程驳回,有一个很重要的起因是计划的接入是非常简单的,惟一要做的事件是在客户端HTML页面的Body元素中退出一段由ARMS提供的统计接入脚本(一段JavaScript代码),就能实现监控数据的主动上报。这其中不波及到任何跟业务层被动埋点的工作,在核桃编程的多条业务线之间推广起来是十分顺利的。基于之前的教训,但凡须要在业务层被动埋点的监控计划,都须要通过行政伎俩来保障多个研发团队在编写代码的时候恪守既定的规定,这样的形式从长期来看都是很难落地的。包含在服务端全链路监控方面,核桃编程也始终遵循业务无侵入的思路,防止被动埋点行为。 接下来,研发人员就能从前端监控控制台全面理解利用端到端的衰弱水平,包含PV/UV状况统计、页面加载速度状况、JavaScript执行状况,API申请成功率等多个方面。以页面加载速度为例,ARMS能够基于客户端主动上报的监控数据,实时展现每一个页面的加载状况。 其中,首次渲染工夫、首屏工夫、Dom Ready等指标都是HTML页面独有的性能指标,遵循业务规范的指标定义。这些指标数据和前端页面衰弱水平非亲非故,影响着最终用户每一次交互行为的理论体验。 通过页面加载瀑布图,可能依照页面加载的程序,直观地展现各阶段的耗时状况。这些指标参数涵盖了网络层面的性能指标,当网络层面呈现性能瓶颈,比方利用零碎的接入带宽不能撑持用户拜访流量的时候,仅仅通过服务端的监控伎俩,是无奈洞察到的,必须依赖于客户端的实时监控数据上报。通过ARMS前端监控,核桃编程能从页面生产时(服务器端状态)、页面加载时和页面运行时这三个方面,全面理解到每一个利用零碎端到端的衰弱水平。 特地重要的是,ARMS前端监控可能从地理位置、浏览器、操作系统、分辨率、网络运营商、利用版本等多个保护,对性能指标进行聚合剖析,从而帮忙核桃编程更好地定位性能瓶颈。比方地理分布视图就能通过对地理位置的聚合剖析,展示全国每一个省的页面首次渲染均匀工夫。当某一个地区的CDN呈现故障的时候,地理分布视图能帮忙核桃编程迅速定位问题的本源,而传统的监控伎俩是齐全没有方法笼罩这类场景的。 JavaScript谬误剖析和API申请剖析也是核桃编程在利用零碎的日常保护中十分关怀的页面衰弱度指标。前者能够展现JavaScript谬误的根本信息和散布状况,并具备回溯用户行为的能力。后者能够展现每个API的调用状况,包含调用成功率、返回信息、调用胜利或失败的均匀耗时等。以后端页面齐全载入后,用户的操作会波及到简单的JavaScript执行,并在页面触发多个API调用,其中还包含对第三方提供的接口调用。 ARMS可能从最终用户的角度,实在还原前端代码执行的残缺现场,帮忙核桃编程疾速定位来自前端的故障源。和页面加载速度统计一样,JavaScript谬误剖析和API申请剖析都可能通过地理位置、浏览器等多种维度进行聚合剖析。在线上编程教育的业务场景外面,客户端的实现蕴含着大量业务逻辑以及云端之间的双向交互,有一些问题只有在特定的浏览器和页面分辨率下才有可能裸露进去,这类问题就特地依赖多维度聚合剖析进行排查。 在熟练掌握ARMS提供的前端可观测性能力之后,核桃编程开始把前端页面衰弱度指标作为日常业务迭代的检测规范,这项工作是通过与所有业务线的灰度公布打算相互配合而进行的。对于生产环境的每一次版本升级,核桃编程都会通过灰度公布的形式实现,先将小规模的用户流量导入新版本进行功能性、稳定性、衰弱性验证,只有满足事后定义的各项指标后,才会逐渐减少导入新版本的用户流量,否则会立刻对版本进行回滚。前端衰弱度的各种指标都是十分重要的掂量维度,而这些指标仅仅通过版本公布前的惯例测试伎俩,是没有方法全面采集到的。核桃编程将前端衰弱度纳入业务迭代的衡量标准,体现着业务迭代过程中的可灰度、可观测、可回滚,这也是在阿里巴巴广为推崇的平安生产三板斧准则。 除了通过ARMS控制台被动的察看剖析,把握各项前端业务指标之外,更重要的事件是在遇到用户体验问题时,如何第一工夫失去告诉和告警,防患于未然。这个诉求通过ARMS欠缺的报警机制能够轻松实现。核桃基于本身对前端衰弱度的了解,以及业界通用的方法论,创立了多种维度的报警规定,比方“最近5钟内均匀页面首次渲染耗时大于1秒”等。当规定被触发时,零碎会以预先指定的报警形式向报警联系人分组发送报警信息,以揭示技术团队及时解决。这些报警规定再配合上对生产故障的分级分类定义,可能帮忙核桃技术团队建设一整套生产故障应答机制,真正实现实线上问题5分钟内发现,10分钟内隔离,30分钟内解决。 核桃编程还积极探索前后端对立链路追踪技术,将API申请从前端收回到后端调用的链路串联起来,实在还原代码执行的残缺现场。这是通过对前端API申请主动注入Trace信息而实现,ARMS前端监控可能在容许API主动上报的前提下,在API申请的Request Header中退出主动生成的TraceID,作为串联前后端链路的标识。这样通过调用的时间轴,能够晓得是网络传输还是后端调用导致申请耗时工夫过长,进一步通过后端利用的线程分析性能,能够洞察每次申请后端的残缺调用链路,对于排查系统故障和性能瓶颈带来了十分大的帮忙。 欠缺的前端可观测体系在帮忙核桃编程缩小了30%以上的运维工作量的同时,还缩短了60%以上的故障定位均匀耗时,极大地晋升了用户体验,为业务继续倒退打下了松软的根底。核桃技术团队将基于本身的技术特点,持续摸索更多前沿的云原生技术,充沛享受云计算带来的红利。 核桃编程正在招聘业务架构师、运维架构师,核桃编程通过优质的课程内容和独创的AI人机双师互动学习辅导零碎,现已成为国内外当先的少儿编程教育公司,产品技术团队多来自于阿里巴巴、百度等顶尖互联网公司;课程研发团队全副出身双一流高校,同时还会集了儿童心理及行为钻研等畛域的顶尖人才。 作者:山猎,阿里云解决方案架构师原文链接本文为阿里云原创内容,未经容许不得转载

January 26, 2021 · 1 min · jiezi

关于chrome:Apache-Flink-在实时金融数据湖的应用

简介: 本文由京东搜索算法架构团队分享,次要介绍 Apache Flink 在京东商品搜寻排序在线学习中的利用实际一、背景在京东的商品搜寻排序中,常常会遇到搜寻后果多样性有余导致系统非最优解的问题。为了解决数据马太效应带来的模型商品排序多样性的有余,咱们利用基于二项式汤普森采样建模,然而该算法仍存在对所有用户采纳统一的策略,未无效思考用户和商品的个性化信息。基于该现状,咱们采取在线学习,使深度学习和汤普森采样交融,实现个性化多样性排序计划,实时更新模型的关参数。 在该计划中,Flink 次要利用于实时样本的生成和 online learning 的实现。在在线学习过程中,样本是模型训练的基石,在超大规模样本数据的解决上,咱们比照了 Flink、Storm 和 Spark Streaming 之后,最终抉择用 Flink 作为实时样本流数据的生产以及迭代 online learning 参数的框架。在线学习的整体链路特地长,波及在线端特色日志、流式特色解决、流式特色与用户行为标签关联、异样样本解决、模型动静参数实时训练与更新等环节,online learning 对样本解决和参数状态解决的准确性和稳定性要求较高,任何一个阶段都有可能呈现问题,为此咱们接入京东的 observer 体系,领有残缺的全链路监控零碎,保障各个阶段数据的稳定性和完整性;上面咱们首先介绍一下京东搜寻在线学习架构。 二、京东搜寻在线学习架构京东搜寻的排序模型零碎架构次要包含以下几个局部: 1、Predictor 是模型预估服务,在 load 模型中分为 static 局部和 dynamic 局部,static 局部由离线数据训练失去,次要学习 user 和 doc 的浓密特色示意,dynamic 局部次要蕴含 doc 粒度的权重向量,这部分由实时的 online learning 工作实时更新。2、Rank 次要包含一些排序策略,在排序最终后果确定之后,会实时落特色日志,将 doc 的特色按程序写入特色数据流,作为后续实时样本的数据源(feature)。3、Feature Collector 的工作是承接在线预估零碎收回的特色数据,对上游屏蔽缓存、去重、筛选等在线零碎特有逻辑,产出 Query+Doc 粒度的特色流。4、Sample join 的工作将下面的 feature 数据、曝光、点击、加购、下单等用户行为标签数据作为数据源,通过 Flink 的 union + timer 数据模型关联成为合乎业务要求的样本数据,算法可依据指标需要抉择不同的标签作为正负样本标记。5、Online learning 工作负责生产上游生成的实时样本做训练,负责更新 model 的 dynamic 局部。 三、实时样本生成Online Learning 对于在线样本生成的时效性和准确性都有很高的要求,同时也对作业的稳定性有很高的要求。在海量用户日志数据实时涌入的状况下,咱们不仅要保障作业的数据延时低、样本关联率高且工作稳固,而且作业的吞吐不受影响、资源使用率达到最高。 ...

January 26, 2021 · 2 min · jiezi

关于chrome:图解浏览器

本文已收录在前端食堂同名仓库Github github.com/Geekhyt,欢迎光临食堂,如果感觉酒菜还算可口,赏个 Star 对食堂老板来说是莫大的激励。 美味值:???????????????????? 口味:仔梅烧小排 01 浏览器架构演进开篇咱们先来简略回顾下历史,从 1993 年公布的第一款“好用”的浏览器 Mosaic,到 1994 年网景公司推出的红极一时的 Navigator 浏览器,图形用户界面化的浏览器终于开始推动了 Web 技术的遍及和倒退。 微软也随后推出了 IE,退出战场并获得浏览器大战“一战”的胜利。战败的网景公司索性将 Navigator 源代码开源,创立了 Mozilla 基金会,并于 2004 年公布了 Firefox 浏览器。 苹果公司于 2003 年公布了 Safari 浏览器,Google 公司于 2008 年公布了 Chrome 浏览器。Chrome 浏览器在浏览器大战的“二战”中技压群雄,拔得头筹。现如今也是前端工程师最青睐的浏览器,没有之一。 Chrome 浏览器从 2007 年以前的单过程架构到当初的多过程架构,浏览器的架构在一直的降级,变得更加稳固、更加晦涩、更加平安。目前 Chrome 的浏览器包含如下过程: 1 个浏览器(Browser)主过程1 个 GPU 过程1 个网络(NetWork)过程多个渲染过程(运行在沙箱模式下)多个插件过程 不过,软件工程可没有银弹。浏览器的架构体系也随着调整变得更加简单,也会有更高的资源占用。 那么如何寻求一种在资源占用和简单架构体系之间的均衡便成为了一个难题。 小孩子才做抉择,鱼和熊掌我都要! Chrome 团队在 2016 年应用“面向服务的架构”(Services Oriented Architecture,简称 SOA)的思维设计了新的 Chrome 架构。 他们将模块重形成独立的服务(Service),服务运行在独立的过程中,想要拜访的话必须应用定义好的接口,通过 IPC 来进行通信。这样的架构无疑更加内聚、松耦合、易于保护和扩大。 02 浏览器导航渲染流程从输出 URL 到页面展现,这两头产生了什么? ...

January 25, 2021 · 2 min · jiezi

关于chrome:无需软件教你用-Chrome-原生工具给网页长截图

通常咱们会应用零碎的截图工具或者浏览器扩大给网页截图,然而实际上Chrome和Safari都曾经内置了网页截图性能,而且反对长图成果。 尽管这个办法也不是完满的,但也是一个触手可得的计划,让你不借助额定工具截图。 关上查看工具按下F12会弹出开发者工具。 抉择命令而后按下快捷键⌘Command + ⇧Shift + P(Windows为Ctrl + Shift + P),在输入框输出screenshot即可看到以下几个选项: Capture area screenshot - 截取抉择局部区域截图Capture full size screenshot - 网页长截图Capture node screenshot - 截取指定节点截图Capture screenshot - 截取可视区域截图截图默认会放到浏览器下载目录中。 当在查看工具里点击右键时其实也能看到截图性能,不过目前只有Capture node screenshot,心愿当前能反对更多截图性能。 手机端截图此外,你还能截取手机成果的长图,首先按下快捷键⌘Command + ⇧Shift + M(Windows为Ctrl + Shift + M)进入手机端浏览模式。 也能够点击上面按钮切换模式: 而后依照前文的截图命令,即可生成你想要的手机长图。 提醒:浏览器也在左近菜单增加了选项,见下图红框地位。 另外这里反对常见的多种设施拜访成果,也能够自定义其余设施尺寸。 赠送小技巧:对于 macOS 截图快捷键全屏截图⇧Shift + ⌘Command + 3 选定区域截图⇧Shift + ⌘Command + 4 拖移十字线以抉择要捕获的屏幕区域。要挪动所选区域,请在拖移时按住空格键。要勾销拍摄截屏,请按下 Esc 键。 捕获窗口或菜单⇧Shift + ⌘Command + 4 + 空格 ...

January 21, 2021 · 1 min · jiezi

关于chrome:如何迁移-Flink-任务到实时计算

简介: 本文由阿里巴巴技术专家景丽宁(砚田)分享,次要介绍如何迁徙Flink工作到实时计算 Flink 中来。通常用户在线下次要应用 Flink run,这会造成一些问题,比方:同一个配置因版本而变动;无奈疾速切换不同版本;无奈从之前的作业复原。 那么如何从线下迁徙到线上呢?本文将通过上面四局部来向大家介绍。 一、如何迁徙:从 Flink run 到流计算平台如下图的线下命令如何迁徙到线上。首先关上 VVP UI,增加根底配置,次要包含:作业名称、Jar URI、一些主要参数和并行度。还能够点击高级配置,配置更多信息。 比方高级配置里的行为配置,分为三局部:降级策略、初始状态和复原策略。降级策略个别抉择Stateless,初始状态抉择Running,复原策略抉择Latest State。 降级策略抉择Stateless,示意针对曾经在运行的作业,编辑并保留配置后,会间接把原作业停掉,而后重新启动一个更新的作业;抉择Stateble,针对正在运行的作业做配置编辑并保留的话,作业会先做一次Savepoint,而后加载新的配置并应用该 Savepoint启动新的作业。复原策略抉择LatestSavepoint,是指作业在暂停状况下,如果再启动,将应用最新的Savepoint启动。下面介绍的是 Flink 配置中比拟重要的局部,上面图片显示的是另外一部分能够设置Checkpoint距离等的配置,接下来是资源配置。日志配置局部能够抉择日志保留地位,不便日后如果作业呈现问题,能够不便的排查问题。 Flink 作业配置实现并启动运行后,如果出现异常,能够通过运行事件查看运行状况和问题。也能够关上 Flink UI的Job Manager,查看日志状况。 二、多Jar状况下,用户如何增加其余依赖的Jar一些用户有自定义依赖且无奈通过 fat jar 解决问题。举个例子,A用户有本人的main Jar和一些其余的Jar,这些Jar的利用场景不一样,那么首先须要在资源管理页面上传Jar包,上传实现之后就能够在页面应用该文件。上传后再到高级配置中,找到“额定依赖的Jar”,下拉并抉择刚刚上传的Jar 包就能够了。 三、用户如何通过配置文件定义作业在资源管理里上传文件,而后在高级配置里选增加依赖,抉择须要的依赖。如果启动函数里,main class是须要读取某个文件,先通过依赖增加文件,而后再依据提醒的形式读取文件。 以上两个形式是搁置用户Jar的形式,jar 和其余文件都能够在这里寄存。 四、如何复用原来的state减速作业复原如果在运行作业时发现问题,个别状况下是停下来而后找到问题修复后再重启。用户须要在创立的时候指定 Checkpoint 须要的 OSS。 如果开启了Checkpoint,后续作业就能够间接从Checkpoint中复原。首先确认高级配置中复原策略抉择LatestState或LatestSavepoint。在这个前提下,能够暂停作业(千万不要进行作业),暂停会触发Savepoint,当再次点击启动时,会从这次Savepoint点复原。 关上 Flink UI ,而后点击作业快照,在作业快照中能够查看 Flink Checkpoint指标,外面会显示Restore的次数和最初一次Restore的地址等信息,可确定作业是从最新的 State 复原。 当作业正在运行,想对以后作业出项拷贝,如何操作呢?在作业控制页面点击Checkpoint,找到历史快照并点击其对应的最右侧的“从该快照复制作业”,那么就实现了把以后作业复制的操作,复制内容包含正在运行作业的Jar 包配置等。点击启动后,能够从作业快照中查看到新作业是从上个作业最近的一次Savepoint中复制启动的。 作者:景丽宁(砚田)原文链接 本文为阿里云原创内容,未经容许不得转载

January 21, 2021 · 1 min · jiezi

关于SegmentFault:闲鱼是怎么让二手属性抽取准确率达到95的

闲鱼是怎么让二手属性抽取准确率达到95%+的?先上成果图1 - 二手属性抽取算法成果Demo(1) 背景闲鱼作为一款C2X的app,站在商品公布的角度,闲鱼商品绝对于淘宝商品的特点有: 轻公布导致商品信息有余 闲鱼采纳图文形容的轻公布模式,投合了用户疾速公布的体验,但也导致了商品结构化信息有余的问题。如果平台心愿更了解商品到底是什么,就须要算法去辨认用户形容的图片和文本。商品具备独特的二手属性 不同于淘宝新品的一手属性(例如品牌、型号、规格参数等),二手属性指的是在商品动手一段时间后,可能反映商品折损/保值状况的属性,比方商品的【应用次数】、【购买渠道】、【包装/配件是否残缺】等。 不同类目有该类目独特的二手属性,比方个护美妆有【保质期】,手机有【屏幕外观】、【拆修状况】,服装类有【是否下过水】等。问题和难点二手属性抽取在NLP畛域属于信息抽取(Information Extraction)问题,通常的做法是拆解为命名实体辨认(NER)工作和文本分类(Text Classification)工作。 二手属性抽取工作的难点有: 不同的类目、不同的二手属性/属性簇,须要构建不同的模型。如果应用有监督学习(Bert家族),打标工作会十分的沉重,开发周期会变得很长。解决方案方法论 在当今NLP环境,仍旧是Bert家族(或Transformer衍生的各种算法)大行其道,霸榜GLUE、CLUE等各大NLP榜单,信息抽取工作也不例外,所以笔者在本计划中的某些场景也应用了Bert家族。不过笔者认为,没有一种算法在各种场景下都是全能的,只有在给定畛域、指定场景下最实用的算法。此外,笔者总结了本人的一套属性抽取的方法论: 句式绝对固定,或者句式受模板限度,如文本形容模板是典型的工夫+地点+人物+事件(某事某地某人做了啥事),用NER,倡议办法:CRF、BiLSTM+CRF、Bert家族、Bert家族+CRF等。句式不固定,但畛域/场景关键词绝对固定,或者有一些关键词模板、俗称、行话等,用文本分类:近义词、近义表述不是特地多的状况(≤几十种到上百种),关键词呈对数正态分布/指数分布(即有很多高频且集中的关键词),倡议办法:正则表达式+规定。近义词、近义表述十分多的状况(≥几百种到上千种),典型的如地名辨认,倡议办法:用Bert家族句式和词语都不固定,典型的如社交评论/聊天的情感剖析,倡议办法:用Bert家族。计划架构 图2 - 二手属性抽取计划架构图 NLP工作 如前所述,将不同的二手属性辨认需要拆解为文本多分类、多标签分类以及NER工作。文本多分类:即“n选1”问题,比方依据文本判断商品是否包邮(二分类)。多标签分类:即同时进行多个“n选1”问题,比方同时判断某手机商品的屏幕外观(好/中/差)和机身外观(好/中/差)。多标签分类通常的做法是对不同标签共享网络层,并将损失函数以肯定权重叠加,因为多个标签之间有肯定水平的分割,成果有时候会比做多个独自的“n选1”问题更好,同时因为是多个属性(属性簇)一起建模,在训练和推断的时候也会更省事。NER:即命名实体辨认。建模办法人工打标阶段 因为打标的人工成本比拟高,须要设法利用团体的AliNLP进行辅助。办法是,首先利用AliNLP的电商NER模型对输出文本进行解析。而后进行拆解,对属于NER工作的二手属性,如保质期/保修期/容量/应用次数/服装格调等,能够间接定位到相干词性或实体的关键词进行BIO标注;对属于分类工作的其它二手属性,则能够在电商NER的分词后果根底上打标,进步人工标注的效率。算法训练阶段 此为计划外围,本计划训练算法次要通过3种路径:(1)应用Albert-Tiny:建模采纳支流对预训练+finetune的计划。因为该模型推断速度更快,用于对QPS和响应要求十分高的实时在线场景。对于NER工作也能够尝试在网络最初面接一层CRF或不接。 Albert:Albert意指“A lite bert”,货真价实,它的长处在训练速度快。 Albert的源码相比Bert的源码根本一模一样,但网络结构有几点重要的区别: Word Embedding层做了因式分解,在词向量上大大减少了参数量。设词表大小为V,词向量长度为H,对Bert,词向量参数量为VH;对Albert,先把词向长度量缩减为E,再裁减为H,参数量为VE+E*H,因为E远小于H,H远小于V,用于训练的参数量失去锐减。跨层参数共享:以albert-base为例,albert会在12层之间共享每层的attention参数或全连贯层ffn的参数,默认是两者都共享。源码中通过tenorflow.variable_scope的reuse参数能够轻松实现。参数共享进一步缩小了须要训练的参数量。 除此之外,Albert还有一些训练任务和训练细节上的优化,此处按下不表。Albert根据网络深度不同分为: - Albert-Large/xLarge/xxLarge:24层 - Albert-Base:12层 - Albert-Small:6层 - Albert-Tiny:4层 一般来说,层数越多,训练和推断耗时都会越久。思考到线上部署的实时性要求更快的推断速度,本计划抉择了最小的Albert-Tiny。其中文推断速度绝对bert-base进步约10倍,且精度根本保留(数据援用自github/albert_zh)。 (2)应用StrutBert-Base:建模采纳支流对预训练+finetune的计划。经测算,在二手属性辨认上,它比Albert-Tiny准确率绝对晋升约1%到1.5%,可用于离线T+1场景。对于NER工作也能够尝试在网络最初面接一层CRF或不接。 StructBert:为阿里自研算法,长处在精度高,GLUE榜单上曾经排到第3名。 Word Structural Objective:StrutBert在Bert的MLM工作根底上,加上了打乱词序并迫使其重构正确词序的工作:论文中是随机抽取一个三元词组(trigram)进行打乱,而后加上了如下公式作为MLM损失函数的束缚。StrutBert的这个灵感兴许来自于网上的一个段子:“研表究明,汉字序顺并不定一影阅响读,事证实明了当你看这完句话之后才发字现都乱是的”。 图4 - Word Structural 的指标函数(援用自StrutBert论文) 本计划之所以抉择StrutBert,是因为团体内有该算法在电商畛域专属的预训练模型(接口),它根据网络深度不同分为: StrutBert-Base:12层StrutBert-Lite:6层StrutBert-Tiny:4层在离线T+1场景下,谋求精度更高而对实时性无太大要求,因而本计划抉择了StrutBert-Base。 本计划之所以抉择StrutBert,是因为团体内有该算法在电商畛域专属的预训练模型(接口),它根据网络深度不同分为: StrutBert-Base:12层StrutBert-Lite:6层StrutBert-Tiny:4层在离线T+1场景下,谋求精度更高而对实时性无太大要求,因而本计划抉择了StrutBert-Base。 (3)应用正则表达式:长处:速度最快,比Albert-Tiny还快10-100倍以上;且在许多句式和关键词绝对固定的二手属性上,准确率比下面两种算法更高;且易于保护。毛病:十分依赖业务知识、行业教训和数据分析对大量正则模式进行梳理。 规定修改阶段========== 辨认后果归一化:对于NER工作,许多辨认进去的后果不能间接应用,须要做“归一化”,例如某件男装衣服的尺码辨认进去为“175/88A”,那么应该主动映射到“L码”。某些二手属性之间可能会存在抵触或依赖,因而在算法辨认之后,须要对辨认后果根据业务规定进行肯定修改。比方某商品卖家宣称是“全新”,然而同时又表明“仅用过3次”,那么“全新”会主动降级为“非全新”(99新或95新,不同类目分级略有不同)。算法部署离线T+1场景:通过ODPS(现名MaxCompute)+UDF的形式进行部署,即算法会通过Python写成UDF脚本,模型文件则作为资源上传到ODPS上。在线实时场景:模型通过PAI-EAS进行分布式部署,数据交互通过iGraph(一种实时图数据库)和TPP实现。算法评估对每个类目标每个二手属性,制订好评测的规范,而后抽样一定量级的数据,交由外包进行人工评估。评估工作通过比照人工辨认的后果和算法辨认的后果是否统一,给出准确率、准确率、召回率等。 最终成果准确率本计划辨认后果通过人工评估,每个类目无论是准确率、精召率都达到了十分高的程度,且误差值均远小于上线限度,并曾经上线利用在闲鱼次要类目标商品上。 成果展现 图5 - 二手属性抽取算法成果Demo(2) 利用场景&后续瞻望二手属性抽取的后果目前已利用的场景包含: 定价场景聊天场景优质商品池开掘搜寻导购个性化商品举荐后续瞻望:目前二手属性抽取总共笼罩闲鱼支流类目商品,随着开发进行,后续打算笼罩到全副类目。目前二手属性抽取次要依赖于文本辨认,闲鱼商品是图文形容,后续能够思考在图片上下功夫,通过图像算法欠缺商品的结构化信息。利用和剖析商品二手属性,造成优质商品规范,裁减优质商品池。作者:渐漓原文链接本文为阿里云原创内容,未经容许不得转载

January 20, 2021 · 1 min · jiezi

关于SegmentFault:怎么提升写代码的能力

简介: 对于程序员而言,我始终认为代码是展示能力的要害,一个优良程序员写的代码,和一个一般程序员写的代码是很容易看出差异的,代码作为程序员的硬实力和名片的展现,怎么晋升写代码的能力始终是一个要害的话题,不过很遗憾这篇文章其实也不是讲具体的步骤、银弹办法、文治秘籍什么的,这篇文章讲讲我本人印象中对我写代码能力晋升比拟大的四段经验,兴许可供参考。 第一段:第一次感触每天亿级零碎的挑战2008 年,HSF 的第二个版本,在过后淘宝最重要的交易中心上线,上线当天造成淘宝网站拜访巨慢,交易类的页面简直打不开,最初靠下线 HSF 才复原。 下线后开始查问题,HSF 的第二个版本基于的是 jboss-remoting,jboss-remoting 在过后的版本里近程同步调用的超时工夫是写死在代码里的 60s,而调用的服务的确会有一些超过 10 几秒的景象呈现,导致了 web 利用解决 web 申请的线程池被这些慢申请给逐步占据,申请沉积,最终呈现出了页面关上十分慢的景象。 查清起因后,决定基于过后的 Mina 重写整个 HSF 的通信,重写的这两个月工夫对我本人写代码的能力有很大的晋升,无论是对网络 IO 方面解决的深刻学习,还是在高并发零碎上的深刻学习,当初想想学习的形式也就是翻各类网络 IO 的科普材料,而后是读 Mina 的源码、Java 网络 IO 的源码,并发这块的学习次要还是靠那本经典的《Java 并发编程实战》,以及读 Java J.U.C 里的代码,这段时间的学习相比以往翻 Think in Java 之类的最大区别是,学习后付诸实践,随着 HSF 这个新的重写的版本的上线,根本算是逐步真正把握了这些局部的代码能力。 除了代码能力的晋升外,失去了另外一个最大的教训就是,对于一个亿级且长时间运行的零碎,很多看起来的小概率的问题都肯定会成为重大的问题,这也是为什么写高并发零碎的难度,要求了必须对本人写的代码,以及本人代码调用到的各种 API 里的实现都十分的分明,这样能力真正确保最终代码的鲁棒性。 第二段:民间“消防队”的故事第二段对我本人写代码能力晋升特地大的经验是在民间"消防队"的那段日子,淘宝在 2009 年故障特地多,但解决故障还没有一个规范的体系和组织,导致很多时候会呈现故障出了都没什么人解决,或者解决效率不高,于是过后有个运维团队的同学拉了一些人组建了一个群,群的名字叫淘宝消防队,用来解决淘宝呈现的各种故障,我很凑巧的也退出了这个群,这个群里还有另外一个整个阿里公认的超级技术大神:多隆。 一开始看到各种故障的时候,压根就不晓得怎么下手,解决故障会须要的通常不仅仅是写代码的能力,还须要对一个零碎全貌要有肯定的把握,例如前几年一篇特地火的文章,当点击搜寻背地产生了什么这样的文章,其实就是要对一个零碎的解决流程特地的相熟,这在解决故障的时候是十分重要的,在有了故障大略在哪个环节后,很重要的就是对这个环节代码运行机制的细节掌控了,这个时候通常来说各种工具十分重要,能够无效的帮忙你晓得具体产生了什么,例如像零碎层面的 top -H 之类的, java 层面的 btrace 等等,都能够让你依据运行状况去定位问题的点。 这段时间我感觉我的晋升就是靠大量的练手,故障的确有点多,一开始就靠看人怎么解决,次要是从多隆这里学,而后是尝试本人解决一些故障,解决的越来越多后缓缓熟练度就下来了,除了解决故障能力的晋升外,因为看了很多因为代码层面造成的故障,对本人在写代码时如何更好的保障鲁棒性,来防止故障,是十分有帮忙的,例如,我看过很多滥用线程池造成创立了大量线程,最终导致线程创立不进去的 case,就会明确本人在用线程池的场景里肯定要十分分明的管制最大的数量,包含沉积的策略等,又例如我看过 N 多的因为自增长容量的数据结构导致的 OOM 的 case,就会明确在写代码的时候不能认为肯定不会产生数据结构增长到超级大,所以不做任何爱护的 case,这个工夫我明确到的就是写一段能运行,实现需求的代码不难,但要写一段在各种状况下都能长期稳固运行的代码是真心不容易,这我感觉是一个职业的写商业系统的程序员和只是写程序玩玩的最大差异。 第三段:重写通信框架2010 年,我从中间件团队来到,去做 HBase,那个时候的 HBase 外面的通信还是用一个非常简单的写法实现的,我想着要么就把以前 HSF 里用的移植到 HBase 里用,这个时候刚好多隆在用 c 给各类 c 的利用写一个通用的通信框架 libeasy,于是就有了一次测试,我记得第一次测试后果看到原来 HSF 外面的通信框架的高并发能力和 libeasy 比相差无比微小,我和多隆便探讨他是怎么实现的,我看看能不能学习下在 Java 这边的版本里也改改,所以有了这段重写通信框架的经验。 ...

January 20, 2021 · 1 min · jiezi

关于chrome:挑战前端知识点HTTPECMAScript

哪吒人生信条:如果你所学的货色 处于喜爱 才会有弱小的能源撑持。 每天学习编程,让你离幻想更新一步,感激不负每一份酷爱编程的程序员,不管知识点如许奇葩,和我一起,让那一颗像到处流荡的心定下来,始终走上来,加油,2021加油!欢送关注加我vx:xiaoda0423,欢送点赞、珍藏和评论 不要胆怯做梦,然而呢,也不要光做梦,要做一个实干家,而不是空谈家,求真力行。 前言心愿能够通过这篇文章,可能给你失去帮忙。(感激一键三连),接管好挑战了吗? 对于HTTP模块1.说说你对HTTP和HTTPS的了解,并说一下它们的端口号是什么好的,HTTP是超文本传输协定,是一个基于申请与响应,无状态的,应用层的协定,常基于TCP/IP协定传输数据,互联网上利用最为宽泛的一种网络协议,所有的www文件都必须恪守这个规范,设计HTTP的初衷是为了提供一种公布和接管HTML页面的办法。 HTTP是一种宽泛应用的网络传输协定,是客户端浏览器或其余程序与web服务器之间的应用层通信协议或者规范tcp,用于从www服务器传输超文本到本地浏览器的传输协定,它能够使浏览器更加高效,使网络传输缩小。 那么HTTPS,它是一种通过计算机网络进行齐全通信的传输协定,通过HTTP进行通信,利用SSL/TLS建设通信,加密数据包。HTTPS应用的次要目标是提供对网站服务器的身份认证,同时爱护替换数据的隐衷与完整性。 https是http的加密版,是以平安为指标的http,在http中退出ssl,平安根底是ssl。 TLS是传输层加密协议,前身是SSL协定。 HTTP通常承载于TCP之上,在HTTTP和TCP之间增加一个平安协定层(SSL或TSL),就是咱们常说的HTTPS。 HTTP特点: 反对客户端或服务器模式,C/S模式; 简略疾速,客户端向服务器申请服务时,只需传送申请办法和门路。申请办法罕用的有GET,HEAD,POST,每种办法规定了客户与服务器分割的类型不同,因为HTTP协定简略,使得HTTP服务器的程序规模小,因此通信速度很快; 比拟灵便,HTTP容许传输任意类型的数据对象,正在传输的类型由Content-Type加以标记; 无连贯,示意限度每次连贯只解决一个申请,服务器解决完客户端的申请,并收到客户端的应答后,就断开连接,采纳这种形式能够节俭传输工夫; 无状态,HTTP协定是无状态的协定,无状态示意协定对于事务处理是没有记忆能力的,短少状态意味着如果后续解决须要后面的信息,则它就必须重传,这样可能导致每次连贯传送的数据量一直减少,另一方面,在服务器不须要先前信息时它的应答就比拟快。 HTTPS特点 它是采纳混合加密技术,两头者是无奈看到明文内容,对内容加密过; 又对身份进行验证,通过证书认证客户端拜访的是本人的服务器; 能够避免传输的内容被中间人假冒或者篡改,保户了数据的完整性。 HTTP的URL是以http://结尾,对于HTTPS的URL是以https://结尾;HTTP是不平安的,而HTTPS是平安的;HTTP无奈加密,而HTTPS对传输的数据进行加密;HTTP无需证书,而HTTPS须要CA机构的颁发的SSL证书。 它们的端口号别离是: HTTP默认的端口号为80,HTTPS默认的端口号为443 那么HTTPS更加平安的因为是:在网络申请中,须要很多服务器,路由器的转发。其中的节点都可能篡改信息,而如果应用HTTPS,密钥在终点站才有。HTTPS之所以比HTTP平安,是因为它利用ssl/tls协定传输。它蕴含证书,卸载,流量转发,负载平衡,页面适配,浏览器适配,refer传递等技术,保障了传输过程的安全性。 https,全称Hyper Text Transfer Protocol Secure,相比http,多一个secure,这一个secure是由TLS(ssl)提供的。https和http都属于application layer,基于tcp以及udp协定,然而又齐全不一样。 http是客户端和服务器端之间数据传输的格局标准,示意“超文本传输协定”小结 无状态协定对于事务没有记忆能力,短少状态示意如果后续须要解决,须要后面提供的信息克服无状态协定缺点的方法是通过cookie和会话保存信息2.http/2你理解多少HTTP/2引入了“服务器端推送”的概念,它容许服务器端在客户端须要数据之前被动将数据发送到客户端缓存中,从而进步性能。 HTTP/2提供更多的加密反对。应用多路技术,容许多个音讯再一个连贯上同时交差。减少了头压缩,因而申请十分小,申请和响应的header都只会用很小的带宽比例。 http/2协定是基于https的,所以http/2的安全性也是有保障的。 头部压缩:http/2会压缩头,如果你同时收回多个申请,他们的头是一样的或是类似的,那么,协定会帮你打消反复的局部。 对于http/2不再应用像http/1.1里的纯文本模式的报文,而是采纳了二进制格局。头信息和数据体都是二进制,统称为帧,头信息帧和数据帧。 数据流:http/2的数据包不是按程序发送的,同一个连贯外面间断的数据包,可能属于不同的回应,必须要对数据包做标记,指出它属于哪个回应。每个申请或回应的所有数据包,称为一个数据流。 多路复用:http/2是能够在一个连贯中并发多个申请或回应,而不必依照程序一一对应,解决了http/1.1中的串行申请,不须要排队期待,也就不会呈现队头阻塞问题,升高了提早,大幅度提高了连贯的利用率。 服务器推送,http/2改善了传送的申请-应答工作模式,服务端不再是被动响应,也能够主动向客户端发送信息了。 http2问题呈现在,多个http申请在复用一个tcp连贯,上层的tcp协定是不晓得有多少个http申请的,一旦产生丢包景象,会触发tcp的重传机制,这样一个tcp连贯中的所有的http申请都必须期待这个丢了的包被重传回来。 第一,http/1.1中的管道传输中如果有一个申请阻塞了,那么队列后申请也通通被阻塞了。第二,http/2多申请复用一个tcp连贯,一旦产生丢包,就会阻塞所有的http申请。 3.说说http常见的状态码五大类的http状态码: 1xx: 提示信息,示意目前是协定解决的中间状态,后续还有操作 2xx: 胜利,报文曾经收到并被正确处理,200, 204, 206 3xx: 重定向,资源地位产生变动,须要客户端从新发送申请 4xx: 客户端谬误,申请报文有误,服务器无奈解决 5xx:服务器谬误,服务器在解决申请时外部产生了谬误 100 Continue 示意持续,个别在发送post申请时,曾经发送了http header之后,服务器端将返回此信息,示意确认,之后发送具体参数信息。200 ok 示意失常返回信息。201 Created 示意申请胜利并且服务器创立了新的资源202 Accepted 示意服务器曾经承受申请,但尚未解决301 Moved Permanently 示意申请的网页已永恒挪动到新地位302 Found 示意临时性重定向303 See Other 示意临时性重定向,且总是应用GET申请新的URI304 Not Modified 示意自从上次申请后,申请的网页伪批改过400 Bad Request 示意服务器无奈了解申请的格局,客户端不该当尝试再次应用雷同的内容发送申请。401 Unauthorized 示意申请未受权403 Forbidden 示意禁止拜访404 Not Found 示意找不到如何与uri 相匹配的资源500 Internal Server Error 示意最常见的服务器端谬误503 Service Unavailable 示意服务器端临时无奈解决申请4.说说http事务流程第一步,域名的解析;第二步,发动tcp的三次握手;第三步,建设tcp连贯后发动HTTP申请;第四步,服务器端响应HTTP申请,浏览器失去HTML代码;第五步,浏览器解析HTML代码,并申请HTML代码中的资源;第六步,浏览器对页面进行渲染并出现给用户。 ...

January 17, 2021 · 2 min · jiezi

关于chrome:一个让你的-YouTube-丝滑般柔顺的插件

Youtube 和 B 站是很多人浏览视频的两个中央。 一开始我还挺喜爱 Youtube 的,不仅是因为能够看到一些其他人看不到的货色,也因为体验比拟棒。而当初,我曾经彻底悲观了。每次看一个十分钟的视频被跳进去四次广告的苦楚你理解么?如果你在看一个须要集中精力思考的视频,那么这种打断真的是十分让人嬉笑。如果不是切实无法忍受这种行为,我也不会应用一些广告屏蔽的插件,毕竟看广告其实也是对 up 主的另外一种反对。 另外 YouTube 居然没有小窗播放。比方我下滑到评论区,视频并不会小窗悬浮播放,差评! 废话不多说了。明天给大家举荐的这个插件名字叫 Enhancer for YouTube。装置地址:https://chrome.google.com/web... 这个插件有 400,000+用户,超过 9000 人做出了评估,评分是五分(满分五分)。 它提供了很多性能以及泛滥的配置项,从外观的配置到性能的配置包罗万象。 还能够配置主题,我把主题换成了暗黑模式。 次要性能有: 应用鼠标滚轮管制音量和播放速度视频去广告(主动或手动)频道白名单(不主动去广告)屏蔽注解(主动或手动)主动切换视频清晰度(能够设定为 4K、HD 或任意清晰度)循环播放视频(残缺循环或局部循环)应用自定义主题款式主动拉伸播放器查看评论时将播放器固定在右下角 执行自定义脚本。。。更多功能期待大家的摸索。

January 15, 2021 · 1 min · jiezi

关于chrome:Chrome-扩展基本学习

前言Chrome 扩大(插件)开发基本知识(V2)。 疾速开始任意地位创立一个我的项目在我的项目根目录创立一个名为 manifest.json 的文件应用任意 IDE 通过 JavaScript 进行我的项目开发将我的项目打包成 .crx 文件装置到 Google 中 Google 中搜寻:chrome://extensions/ 关上扩大程序右上角开启开发者模式点击打包扩大程序并将对应的我的项目文件夹打包。或间接应用文件夹的模式装置到 Google 中 Google 中搜寻:chrome://extensions/ 关上扩大程序右上角开启开发者模式点击加载已解压的扩大程序并抉择对应的我的项目文件夹当初你能够在 Google 中应用你的扩大程序了 ReferenceDoc Chrome 官网入门文档API Chrome 官网 API 参考非官方中文版 API 参考

January 11, 2021 · 1 min · jiezi

关于chrome:从打字机效果的-N-种实现看JS定时器机制和前端动画

 首先,什么是打字机成果呢?一图胜千言,诸君请看: 打字机成果即为文字一一输入,实际上就是Web动画。在Web利用中,实现动画成果的办法比拟多,JavaScript 中能够通过定时器 setTimeout 来实现,css3 能够应用 transition 和 animation 来实现,html5 中的 canvas 也能够实现。除此之外,html5 还提供一个专门用于申请动画的 API,即 requestAnimationFrame(rAF),顾名思义就是 “申请动画帧”。接下来,咱们一起来看看 打字机成果 的几种实现。为了便于了解,我会尽量应用简洁的形式进行实现,有趣味的话,你也能够把这些实现革新的更有逼格、更具艺术气味一点,因为编程,原本就是一门艺术。 打字机成果的 N 种实现实现一:setTimeout() setTimeout版本的实现很简略,只需把要展现的文本进行切割,应用定时器一直向DOM元素里追加文字即可,同时,应用::after伪元素在DOM元素前面产生光标闪动的成果。代码和效果图如下: <!-- 款式 --><style type="text/css"> /* 设置容器款式 */ #content { height: 400px; padding: 10px; font-size: 28px; border-radius: 20px; background-color: antiquewhite; } /* 产生光标闪动的成果 */ #content::after{ content: '|'; color:darkgray; animation: blink 1s infinite; } @keyframes blink{ from{ opacity: 0; } to{ opacity: 1; } }</style><body> <div id='content'></div> <script> (function () { // 获取容器 const container = document.getElementById('content') // 把须要展现的全副文字进行切割 const data = '最简略的打字机成果实现'.split('') // 须要追加到容器中的文字下标 let index = 0 function writing() { if (index < data.length) { // 追加文字 container.innerHTML += data[index ++] let timer = setTimeout(writing, 200) console.log(timer) // 这里会顺次打印 1 2 3 4 5 6 7 8 9 10 } } writing() })(); </script></body> ...

January 11, 2021 · 4 min · jiezi

关于chrome:2020-年-Chrome-开发者峰会的亮点

2020 年的Chrome 开发者峰会和今年有所不同,往年是在线上召开的,每次谈话大概十分钟,探讨规模更大。尽管我没有在第一工夫观看会议的直播,然而看回放也不会错过这些亮点。 所有的回放在这里:https://developer.chrome.com/... 通过“Core Web Vitals”简化了性能指标咱们都晓得 Chrome 有大量的性能指标,能够用它们来跟踪对于网站性能的所有内容。只管划分的粒度使咱们可能深入研究咱们可能须要跟踪的特定区域,这样是十分好的,但有时这些性能指标有些令人望而生畏。 为了解决这个问题,Chrome 小组称提供了名为“Core Web Vitals”的解决方案。上面是三个性能指标,它们是跟踪以下要害因素: 首次内容绘制(FCP):掂量加载体验首次输出提早(FID):掂量互动体验累积版式移位(CLS):掂量视觉稳定性 展望未来,Lighthouse 性能得分将会更看重这些指标,所以十分值得关注。 第一天 CDS 的大部分工夫都是围绕着这些指标进行探讨的,次要内容是如何跟踪并解决常见问题。如果想理解更多细节能够看这两个视频: State of speed tooling (by Elizabeth Sweeny and Paul Irish)Fixing common Web Vitals issues (by Katie Hempenius)新CSS属性的性能持续以性能为主题,还有能给你网页提供更好性能的新 CSS 性能。 content-visibility 属性容许咱们通知浏览器应该在何时去渲染元素。如果值是 auto,它就通知浏览器在视口可见之前先不要渲染元素。这意味着如果浏览器最开始只须要渲染首屏的内容,那么将会将大大放慢页面加载的速度。在 Jake Archibald 的演讲 Beyond fast 中,他提到仅通过这个属性,就把 HTML Standard 布局工夫从 50秒变为 400 毫秒! 为了避免潜在的“累积布局偏移”的问题, content-visibility 属性须要与 contain-intrinsic-size 属性协同工作。因为浏览器并未齐全加载元素,因而在须要渲染元素时可能会产生一些变动。为了最大水平地缩小页面上产生的移位,即便没有渲染内容,也能够用 contain-intrinsic-size属性指定元素的尺寸。 .below-fold-element { content-visibility: auto; contain-intrinsic-size: 0 500px; /* set height to 500px */ } 你能够把这个属性想像成通过为媒体元素增加 width 或 height 的形式来保留空间,以便在最终加载媒体时页面不会产生位移。 ...

December 30, 2020 · 2 min · jiezi

关于chrome:Chrome-提示您的连接不是私密连接-的解决办法

在以前的 Chrome 版本中,呈现 SSL 证书谬误后,只须要点击“高级”-“持续拜访”即可失常拜访网站。 但在新版的 Chrome 中,Chrome 不信赖这些自签名的 SSL 证书,为了平安起见,间接移除了该操作禁止拜访。 解决办法是在以后页面中(不是在地址栏)用英文模式键盘间接输出 thisisunsafe ,页面会主动刷新后失常拜访。 该命令的意思是你通知浏览器,你曾经理解并确认这是个不平安的网站,但仍要拜访。

December 29, 2020 · 1 min · jiezi

关于chrome:Google-Chrom版本升级后站内下载http链接的资源弹窗一闪不下载的问题

下载资源时遇到弹窗一闪不下载的问题明天遇到了一个问题,在网站外部下载资源,之前都是好好的,然而最近降级的Google Chrom浏览器的版本后,就呈现了弹窗一闪不下载的问题,相干搜寻后发现问题是因为,新版本的Chrom认为某些网站误导用户,认为文件http的下载链接是平安的。Chrome将确保安全页面(即HTTPS页面)才可能下载平安文件。 为此,谷歌将会逐渐禁止Chrome浏览器下载非HTTPS的不平安文件,一开始可能会提醒下载正告,最终会齐全阻止用户下载。 所以起因是Chrom认为应用非https链接下载文件是不平安的,在新版本中阻止了用户下载。 那么解决办法有两个 1.把下载链接更新为https2.调整本地浏览器的下载安全级别调整本地浏览器的下载安全级别在浏览器中输出chrome://flags/ 找到#treat-unsafe-downloads-as-active-content选项,而后抉择Disable之后重启浏览器后,再次下载http文件就能够了 本篇文章如有帮忙到您,请给「翎野君」点个赞,感谢您的反对。

December 15, 2020 · 1 min · jiezi

关于chrome:前端内存监控-使用Performance工具

目录内存治理为什么要监控??Performance工具应用流程内存问题 产生内存问题的景象及实质界定内存问题的规范监控内存的几种形式 浏览器工作管理器Timeline时序图记录堆快照查找拆散DOM(能够察看内存泄露) DOM存在的几种状态?实例怎么解决拆散DOM?判断是否存在频繁的垃圾回收(须要用不同的工具) 为什么要判断?具体怎么用监控判断?这里讲到的是应用Performance工具去进行监督内存和垃圾回收的状况,如果对内存治理,垃圾回收以及GC不太懂的请参考文章 JavaScript —— 内存治理及垃圾回收 , 上面开始进入正题 内存治理为什么要监控?GC的目标是为了实现内存空间的良性循环,良性循环的基石是对内存空间正当应用。因为HTML中没有提供内存操作的API,所以时刻关注内存变动能力确定是否正当,咱们能够通过Performance这个工具定位问题所在,Performance工具提供多种监控形式,能够时刻监控内存。 Performance工具应用流程关上浏览器输出指标网址,这里用Chrome进入开发人员工具面板,抉择性能Performance开启录制性能,拜访具体界面执行用户行为,一段时间后进行录制取得报告,剖析界面中记录的内存信息 上面的截图,能够看到内存Memory的选项进去的折线图就示意了内存的时候状况,有升有降就是失常的工作: 内存问题产生内存问题的景象及实质限定以后网络问题失常的状况下: 呈现的景象存在的问题页面呈现提早加载或者经常性暂停内存有问题,与GC频繁的垃圾回收操作是有关联的,肯定存在代码中有让内存爆掉的状况页面持续性呈现蹩脚的性能存在内存收缩,以后界面为了达到最佳应用速度,会申请肯定的内存空间,这个内存空间大小超过了下限页面的性能随工夫缩短越来越差随同内存泄露界定内存问题的规范内存泄露 :内存应用继续升高内存收缩 :以后应用程序自身为了达到最优成果须要肯定的内存空间,兴许与以后设施自身硬件不反对无关,所以产生了性能上的差别,须要去判断是程序的问题还是设施的问题。须要多做测试,在少数设施上都存在性能问题阐明程序自身有问题。频繁垃圾回收 :通过内存变动图进行剖析监控内存的几种形式浏览器工作管理器以数值的模式将程序在执行的过程中内存的变动提现进去 在浏览器中 -> shift+Esc -> 右键选中【JavaScript应用的内存】 第一列的内存是原生内存【DOM节点占据的内存】,这个数据增大示意创立了新的DOM节点。最初一列JavaScript内存是堆内存,界面中所有可达对象正在应用的内存大小。这个数据增大示意要么在创立新对象,要么对象在一直的增长。上面进行一下实例: <!--创立一个长度很大的数组--><body> <button id="add">Add</button> <script> const add = document.getElementById('add') add.onclick = function() { let arrList = new Array(1000000) } </script></body> 点击按钮晓得内存会增大,是因为咱们创立了很大的数组。之后的脚本,能够拿这个去进行监控。 Timeline时序图记录下面的办法只能说咱们的内存存在问题,然而无奈更准确的定位什么工夫产生的,和那些代码有关系。咱们能够通过Timeline时序图间接把以后应用程序的走势以工夫点的形式出现进去。 上面进行一下实例: <body> <button id="btn">Add</button> <script> const arrList = [] function test() { for( let i = 0 ; i < 100000; i++) { document.body.appendChild(document.createElement('p')) } arrList.push(new Array(1000000).join('x')) } document.getElementById('btn').addEventListener('click',test) </script></body>进入页面,关上performance进行录制,点击三次按钮,进行录制。 ...

December 13, 2020 · 1 min · jiezi

关于chrome:31chrome谷歌浏览器无界面运行scrapysplashsplinter

【百度云搜寻,搜各种材料:http://www.lqkweb.com】【搜网盘,搜各种材料:http://www.swpan.cn】1、chrome谷歌浏览器无界面运行 chrome谷歌浏览器无界面运行,次要运行在Linux零碎,windows零碎下不反对 chrome谷歌浏览器无界面运行须要一个模块,pyvirtualdisplay模块 须要先装置pyvirtualdisplay模块 Display(visible=0, size=(800, 600))设置浏览器,visible=0示意不显示界面,size=(800, 600)示意浏览器尺寸 # -*- coding: utf-8 -*-import scrapyfrom scrapy.http import Request,FormRequestfrom selenium import webdriver # 导入selenium模块来操作浏览器软件from scrapy.xlib.pydispatch import dispatcher # 信号散发器from scrapy import signals # 信号class PachSpider(scrapy.Spider): #定义爬虫类,必须继承scrapy.Spider name = 'pach' #设置爬虫名称 allowed_domains = ['www.taobao.com'] #爬取域名 def __init__(self): #初始化 from pyvirtualdisplay import Display display = Display(visible=0, size=(800, 600)) display.start() self.browser = webdriver.Chrome(executable_path='H:/py/16/adc/adc/Firefox/chromedriver.exe') #创立谷歌浏览器对象 super(PachSpider, self).__init__() #设置能够获取上一级父类基类的,__init__办法里的对象封装值 dispatcher.connect(self.spider_closed, signals.spider_closed) #dispatcher.connect()信号散发器,第一个参数信号触发函数,第二个参数是触发信号,signals.spider_closed是爬虫完结信号 #运行到此处时,就会去中间件执行,RequestsChrometmiddware中间件了 def spider_closed(self, spider): #信号触发函数 print('爬虫完结 进行爬虫') self.browser.quit() #敞开浏览器 def start_requests(self): #起始url函数,会替换start_urls return [Request( url='https://www.taobao.com/', callback=self.parse )] def parse(self, response): title = response.css('title::text').extract() print(title)留神:Linux零碎下会呈现谬误 ...

November 10, 2020 · 1 min · jiezi

关于chrome:Chrome-的小恐龙游戏被我破解了

一个阳光明媚的周末,透光的窗帘把我从睡梦中叫醒,大脑说明天是周六,能够慵懒个一上午,于是开心地关上我的 Mac 筹备看两集 Rick and Morty 再起床洗漱。 我急不可待关上了对应的网站,发现浏览器提醒 No internet,这才发现因为我的动作太过于行云流水,电脑还没来得及连上 wifi 于是我决定重温一下这款经典的游戏。 科普:Chrome 浏览器是 Google 家的官网浏览器,应用体验全世界南波万。当用户在无网络时拜访某一网址,浏览器会提醒“无网络链接”(也就是下面这张图),按下空格键,就会唤醒一个小恐龙跑步刷分的游戏。如果在有网络连接时也想玩的话,能够间接在地址栏输出:chrome://dino出于职业自身的敏感和好奇,我忽然心生疑难:这应该是用 JS 做的吧? 我趁势关上控制台,不如先看一下所有的全局变量? 太多了,我可没这个急躁... 我进行了操作,开始思考这所有的可行性: 我在干什么?尝试自定义这个游戏为什么要看全局变量?因为假如对于游戏的对象被裸露在了全局如果没裸露在全局?行,那我就放弃了(周末的晚上我可不想在 sources 外面扒源码)也就是说,如果没有在全局变量里找到那个对象,我就能够选择性放弃了。 再看一下下面这张图,不难发现,这 251 个全局变量,有很多都是老朋友了,name、history、location、onclick、onerror... 这些变量显著和这只小恐龙没啥关系,打印进去纯正是来充个数,还节约了我找指标的工夫,所以我遇到了第一个问题:如何疾速找到由开发者自定义的全局变量? 如果我有一个失常的 window...不对,不必如果,新开一个空窗口不就得了! 在新关上窗口的控制台,我失去了这样的后果: 也就是说,在这个恐龙快跑的小游戏里,Google 的前端工程师向 window 注入了 最多 55 个全局变量(251-196)... 为什么说最多 55 个?因为 Chrome 的版本以及装置的 Chrome 插件都会影响全局变量的个数,比方 React 开发者工具就会向 window 中注入两个全局变量。 于是问题来到了:怎么把这 55 个被注入的全局变量拿过去呢?复制粘贴之后再一个一个比对?太 low 了,让我想想... 在原有窗口的根底上,再搞一个新窗口...这不就是 iframe 吗!iframe 尽管没有 window,然而它有 contentWindow,原则上来说,属性差异应该不大。所以当初只须要创立一个 iframe,拿它外面 contentWindow 的全局变量去过滤以后 window 的全局变量,就能够筛选出那多余的 55 个“嫌疑人”了。 ...

November 6, 2020 · 1 min · jiezi

关于chrome:Chrome浏览器如何查看-Shadow-Dom-结构

Chrome浏览器如何查看 Shadow Dom 构造如果咱们编写如下的代码: <div> <input id="foo" type="range"/> </div> <div> <video src="https://www.w3school.com.cn/i/movie.ogg" controls="controls"> your browser does not support the video tag </video> </div>在页面中渲染出如下的 UI: 一个滑块(slider)以及一个视频(video)元素。然而咱们会发现其实咱们并没有编写 input 的款式,input渲染进去应该是一个输入框才对。然而写 type 为 range之后咱们就会看到一个滑块的 UI 成果。以及视频元素里咱们没有非凡解决播放按钮,视频时常,以及其余的管制按钮元素。 那这些元素是怎么生成的呢?咱们关上 chrome 的 devtools 之后审查元素:也没有看到对应的元素以及 dom 构造。 其实这就是所谓的 Shadow Dom,浏览器暗藏了这一部分的实现。并且封装了实现的细节,包含款式局部也做了隔离。 那咱们如何可能查看这些元素的构造呢?在Chrome浏览器中关上开发者调试工具: 勾选如图当中的 Show user agent shadow DOM。而后再去审查元素: 此时,咱们就可能看到如图当中的 dom 构造啦!!! 后续会再深刻探讨波及到相应的 Shadow DOM知识点。

October 22, 2020 · 1 min · jiezi

关于chrome:Chrome-设置黑色模式

背景在 MAC 上设置了 深色模式 (零碎偏好设置 => 通用 => 深色), 很多 App 能主动把主题替换成深色模式,然而 Chrome 浏览器却没有更新模式(红色背景)。平时写代码习惯了彩色主题,红色跟彩色比照太强,而且早晨看亮色真的太伤眼睛,所以折腾着把 Chrome 替换成 彩色模式。 通过插件更新彩色模式之前有过一段时间想换成彩色模式, 在 Chrome 商店上找了一些主题和插件。然而换过好几个主题, 很多装置下来根本都是只边框换了色彩,网页内容和款式都没有变动,没有成果。 尝试找了一些插件,有两三个插件可能全局批改 Chrome 的全局网页款式,一些没有记得住, 只留下一个集体应用体验最好的插件: Super Dark Mode 应用办法: 装置实现后, 在工具栏点击该插件, 选中 "选项"后, 对网页款式进行配置, 并配置失效站点(反对主动工夫开启和自定义款式): 把款式设置成 Solarized-Color-Scheme 后, 整体看着相当难受。然而有时一些网站,款式有重叠(比方 Github), 而后看着怪顺当的。 通过 Chrome 设置更新彩色模式这是明天刚找到的另外一个办法, 也是官网的推出的彩色模式。 这个 feature 其实上线一段时间了, 只是当初才发现。 Google Chrome78 版本的时候, 就曾经更新彩色模式, 所有网站都能够把款式改为彩色。 设置彩色模式步骤:更新 Chrome 浏览器到 78 以上版本在网址栏输出 Chrome 彩色模式指令: chrome://flags/#enable-force-dark, 点击 Enter 键后就进入 彩色模式配置页: ...

October 1, 2020 · 1 min · jiezi

关于chrome:编程中寻找成就感哪个编程岗位适合您

咱们每个人都领有独特的天才、技能和趣味。找到可能齐全施展这些的岗位能够带给咱们极大的能源以及成就感。但通常,咱们会发现自己所处的岗位非常一般,这导致咱们跳槽、转行以及感触到不满的恶性循环。如果您想转行(或开始新的职业),那么您会发现那里有各种各样的编程岗位,因为近年来岗位品种或“业余”急剧减少。 即使编程是一种必不可少的技能,但它已不再只是一个单纯的“构建”的角色。 做好布局、打算再求职,您不仅是找一份工作,而是一份适宜本人的职业 这样做的益处是,依据本身趣味与劣势匹配,让您更容易找到适宜本人的工作,您的短处及激情会展示进去。以下是波及编程技能的最常见题目的分类及其通常蕴含的内容。 (留神:此列表并非详尽无遗,因为岗位名称和职能取决于公司及其文化。该列表是基于我在网络技术公司负责工程职位的集体察看得出的。) _ A _ 软件/产品工程师(网络/全栈/后端和前端) 通常是大多数学习编程者的首选,可能构建新技术的兴奋是一大吸引力。您可能会沉迷在算法中,并且须要熟练地编写洁净且最佳的代码。 依据公司的不同,这些岗位还会有更多的分支。 例如,前端和后端通常有很大的不同,前端岗位更偏向于视觉/ UX。 全栈有千篇一律的办法,在找到适宜本人的工作前进入此类岗位不失为一个好路径。 现实状况:您是构建者-您喜爱构建新技术和零碎 _ B _ 数据工程师 后端工程师的一种更业余的模式。如果您发现自己更喜爱信息系统而不是产品性能,那么这很适合。您将通过构建和保护数据库系统来促成数据基础架构和剖析。对于更喜爱以数据为核心而不是产品自身的构建者而言,这是一个很好的岗位。 现实状况:您喜爱设计和构建模型和零碎 _ C _ 数据科学家/分析师 该岗位专一于剖析而不是构建。因而,如果您的抱负在于扩充企业影响力而不是为客户构建产品,那么这可能是一个不错的抉择。因为其目标,该岗位可能具备更多的探索性方面,通常有着商业智能的职能。如果您是那种热衷于寻求知识和揭开谜团的人,那么这能够为您带来成就感。与数据分析师岗位不同,数据科学家岗位通常有机器学习的须要。 现实状况:您是数学专家、有创造力并且喜爱寻找答案 _ D _ 数据可视化 此岗位在数据新闻学中很常见,认为是前端工程与数据分析师之间的联合。您须要具备创造力,较好审美并且对数据充满热情。随着世界上越来越多的数据存在,对于企业用户而言,无效的视觉传播(称为“讲故事”)的需要每天都变得越来越显著。这类工作通常也是许多数据迷信/分析师岗位的一个方面。 现实状况:您具备创造力、同理心并且具备较强的设计能力 _ E _ 特定领域专家(平安/iOS/Android/ML/VR/AI等) 这些是软件工程岗位,专一于特定畛域。通常,您须要在特定畛域领有更宽泛的教训和常识能力负担这些岗位。如果您喜爱深入研究一种技术(认为深度优先而不是广度优先),那么从实质上讲,它非常适合您。因而,如果您心愿领有多种抉择,可能不适宜您。这种岗位的毛病是,因为它的通用性较差,因而您的抉择可能会受到更多限度。同时,因为它的泛化水平较低,因而您可能具备较高的创收后劲。 现实状况:您是一名构建者,想成为业余畛域的专家 _ F _ 品质工程师 此岗位通常波及应用诸如Selenium,JMock,Pytest等框架编写测试套件。此岗位的目标是确保开发的软件可能按预期工作并且没有谬误。尽管您不会间接应用该产品,然而在理论公布任何产品性能之前,您的工作至关重要。品质检测当然并不适宜每个人,但如果您喜爱精心测试技术以发现问题而不是解决问题,那可能非常适合品质检测。 现实状况:您重视细节、喜爱测试并擅于发现问题 _ G _ 网站可靠性/基础架构工程师 此岗位通常波及应用诸如Selenium,JMock,Pytest等框架编写测试套件。此岗位的目标是确保开发的软件可能按预期工作并且没有谬误。尽管您不会间接应用该产品,然而在理论公布任何产品性能之前,您的工作至关重要。品质检测当然并不适宜每个人,但如果您喜爱精心测试技术以发现问题而不是解决问题,那可能非常适合品质检测。 现实状况:您重视细节、喜爱测试并擅于发现问题 _ H _ 网站可靠性/基础架构工程师 对于基于Web的服务,您将确保服务放弃安稳运行。对于SaaS公司而言,停机工夫或性能问题可能会造成微小的代价,因而这可能是令人难以置信的低压岗位。如果您在这样的挑战中成长并喜爱应用网络技术,那么这将非常适合您。 现实状况:您能在低压的环境中放弃镇定和成长 _ I _ DevOps 这是一个桥接软件开发和IT经营的岗位。您可能负责设计对代码库,工具等的拜访,并帮忙开发人员设计环境。该岗位可能波及构建外部工具和改良流程。您可能会与开发人员严密单干,并且须要成为良好的沟通者能力在这个岗位中蓬勃发展。 现实状况:您对开发者工具和流程感兴趣 _ J _ 开发者倡导者 这种岗位就像开发者社区的大使一样,是社交岗位,专一于向开发人员推广工程工具。您可能会常常去流动,演示或关注论坛来答复问题。如果您喜爱解释/讲授技术概念,则非常适合。在负责社交岗位时,您通常只在开发人员社区内进行社交。 现实状况:您擅于交际,喜爱数学和加入技术流动 _ ...

September 18, 2020 · 1 min · jiezi

关于chrome:谷歌浏览器Software-Reporter-Tool长时间占用CPU解决办法

如下图所示,大家是否在应用谷歌浏览器的过程中发现CPU风扇狂转,关上工作管理器发现一个名为software_reporter_tool.exe的软件占用了一半的CPU资源!这几乎不能忍,依照上面教程,能够解决这个令人苦恼的问题。 什么是Software Reporter Tool Software Reporter Tool其实就是Chrome的清理工具,用于清理谷歌浏览器中不必要或歹意的扩大,应用程序,劫持开始页面等等。当你装置Chrome时,Software_reporter_tool.exe也就会被下载在SwReporter文件夹下的Chrome利用数据文件夹中。这个软件在运行的过程中可能会长时间地占用CPU,导致高CPU使用率。咱们尽管能够通过工作管理器手动完结过程或者抉择删除SRT,但这都不是短暂的解决办法。因为前者过一段时间它又会再次运行,后者在浏览器更新的时候就又会从新被下载下来。查问该文件,发现software_reporter_tool.exe会扫描零碎,相似Chrome的一个打算工作,每周启动扫描一次,运行大概20-25分钟。 敞开Software Reporter Tool的办法 上面教大家两种敞开Software Reporter Tool的办法,操作难度由易到难,大家能够顺次试一试,如果前一种办法不论用,就用后一种办法。 办法一:批改manifest.json文件 批改 Chrome 设置,“ 将应用状况统计信息和解体报告主动发送给 Google ”的选项敞开,如果此办法有效就持续批改manifest.json文件。 批改此目录下的manifest.json文件,依据本人电脑的Chrome装置目录自行调整:C:\\Users\\Administrator\\AppData\\Local\\Google\\Chrome\\User Data\\SwReporter\\36.184.200将“allow-reporter-logs”: true 批改为 “allow-reporter-logs”: false 办法二:批改software_reporter_tool.exe的属性 1、进入SRT目录,默认状况下它位于以下目录: C:\Users\[YourName]\AppData\Local\Google\Chrome\User Data\SwReporter\[版本]\software_reporter_tool.exe这是我电脑的目录,win7零碎:`C:UsershaoAppDataLocalGoogleChromeUser DataSwReporter83.237.200` 咱们还能够通过win+r键关上运行命令窗口并输出以下命令疾速找到它:`%localappdata%GoogleChromeUser DataSwReporter`2、右键单击software_reporter_tool.exe抉择属性 3、转到“平安”选项卡 4、点击“高级”5、点击“禁用继承”6、抉择"从此对象中删除所有继承的权限",之后一路点击“确定”“确定”。

August 20, 2020 · 1 min · jiezi

关于chrome:Chrome-扩展-如何即时更新内容脚本

扩大装置、更新、卸载后要求刷新网页甚至重开浏览器,不管对用户还是对开发者,都是不悦的抉择。 在 manifest.json 里显式申明 content_scripts,能够轻易地保障每一个匹配的标签页都被注入且只注入一次指定的内容脚本。但它有个显著的缺点,就是在用户装置或更新扩大后,新的内容脚本无奈在网页刷新前载入。 通过 chrome.tabs.executeScript 编程式注入,则存在多个问题,一是新创建标签页、刷新标签页事件须要须要侦听,二是在用户更新扩大后,已注入的内容脚本与新的内容脚本存在抵触。 注入内容脚本的各个办法的独特问题,首先是,更新或卸载前曾经注入的内容脚本,不会主动 “打消”,其注入的 DOM 元素也不受影响。此时,如果内容脚本尝试与后端脚本(background scripts)通信,就会报错。 其次是,脚本注入的可供选择的机会不多。document_start 在 CSS 加载后、DOM 以及原页面脚本运行前注入,document_end 在 DOM 加载实现后注入,而 document_idle 在 document_end 和 window.onload 之间的某个时刻[1]注入,只有这三个选项,须要加工。 [1] 指 “DOMContentLoaded 触发 200 毫秒” 或 “window.onload 触发” 这两条件中任一条件成立的时刻。参阅:(line 176-191) script_injection_manager.cc - Chromium Code Search申明式注入脚本的改良空间不大、不多,本文革新编程式注入办法,来实现内容脚本的即时更新。请确保在应用本文提及的相干 API 时曾经在 manifest.json 中申请了相干权限。 保障内容脚本的注入首先须要在扩大加载时就将内容脚本注入到可注入的标签页里。这样才能够在扩大装置实现或更新实现后,让新的内容脚本立刻开始工作。 /* background script. */const scriptList = [ 'foo.js', 'bar.js' ];const injectScriptsTo = (tabId) => { scriptList.forEach((script) => { chrome.tabs.executeScript(tabId, { file: `${script}`, runAt: 'document_start', // 如果脚本注入失败(没有该标签页权限之类)且没有在回调中查看 `runtime.lastError`, // 就会报错。本例没有其它简单的逻辑,不须要记录注入胜利的标签页,能够这样糊弄一下。 }, () => void chrome.runtime.lastError); });};// ...// 获取全副关上的标签页。chrome.tabs.query({}, (tabList) => { tabList.forEach((tab) => { injectScriptsTo(tab.id); });});// ...留神,你须要在 manifest.json 中申明 tabs 权限才能够应用 tabs.executeScript 办法将脚本注入非流动标签页。侦听标签加载事件太长不看版:侦听 webNavigation.onCommitted 事件。 ...

August 18, 2020 · 3 min · jiezi

关于chrome:Chrome新增的cookie属性SameSite

明天在chrome浏览器中察看申请信息时发现了这样一个正告: 咦,看起来像是阻止了我的 cookie 发送。通过查问方知,原来谷歌为了避免CSRF攻打,曾经逐渐开始启用 SameSite 这个cookie属性,以更强制的伎俩来升高 CSRF 的危险。而这个个性从76版本后,就曾经开始逐渐退出到 chrome 稳定版当中了。我看了下本人的 chrome,赫,都曾经 84版了,必然命中这个个性了。 咱们去chrome开发工具里看一下cookie的属性家族。哇看起来,cookie属性家族真是越来越宏大了: SameSite 是干嘛的咱们来看下 sameSite 到底是个什么鬼货色。从MDN文档能够看到: samesite能够阻止浏览器在跨域申请里携带cookie。 在默认状况下,该属性的值是 Lax,即松散的意思,这个所谓的松散绝对于以前来说其实并不松散,它是 只容许 GET 跨域申请携带 另外一个值是 strict,即严格模式,严格标记将阻止cookie被浏览器发送到所有跨域指标网站,即便是惯例的GET申请。 怎么绕过这个限度呢尽管绕过是不平安的。然而有些场景是没有太严格的要求的,例如统计日志数据的 cgi。除了上述2个值之外,还能够将他申明为 none。通过显式申明SameSite = None,开发人员依然能够不受限制的应用跨域cookie。 浏览器反对状况从Chrome 76开始,通过启用默认默认cookie标记,该性能将可用。从2020年7月14日开始,此性能将逐渐向Stable用户推出。但MacOS上还有BUG(如果设置为none,成果会变成strict)。另外一个bug就是我本人电脑上加上samesite进行设置cookie是有效的,目前还不分明起因,如果有大佬晓得为啥不失效,还请心愿大佬赐教。

August 16, 2020 · 1 min · jiezi

关于chrome:Chrome新增的cookie属性SameSite

明天在chrome浏览器中察看申请信息时发现了这样一个正告: 咦,看起来像是阻止了我的 cookie 发送。通过查问方知,原来谷歌为了避免CSRF攻打,曾经逐渐开始启用 SameSite 这个cookie属性,以更强制的伎俩来升高 CSRF 的危险。而这个个性从76版本后,就曾经开始逐渐退出到 chrome 稳定版当中了。我看了下本人的 chrome,赫,都曾经 84版了,必然命中这个个性了。 咱们去chrome开发工具里看一下cookie的属性家族。哇看起来,cookie属性家族真是越来越宏大了: SameSite 是干嘛的咱们来看下 sameSite 到底是个什么鬼货色。从MDN文档能够看到: samesite能够阻止浏览器在跨域申请里携带cookie。 在默认状况下,该属性的值是 Lax,即松散的意思,这个所谓的松散绝对于以前来说其实并不松散,它是 只容许 GET 跨域申请携带 另外一个值是 strict,即严格模式,严格标记将阻止cookie被浏览器发送到所有跨域指标网站,即便是惯例的GET申请。 怎么绕过这个限度呢尽管绕过是不平安的。然而有些场景是没有太严格的要求的,例如统计日志数据的 cgi。除了上述2个值之外,还能够将他申明为 none。通过显式申明SameSite = None,开发人员依然能够不受限制的应用跨域cookie。 浏览器反对状况从Chrome 76开始,通过启用默认默认cookie标记,该性能将可用。从2020年7月14日开始,此性能将逐渐向Stable用户推出。但MacOS上还有BUG(如果设置为none,成果会变成strict)。另外一个bug就是我本人电脑上加上samesite进行设置cookie是有效的,目前还不分明起因,如果有大佬晓得为啥不失效,还请心愿大佬赐教。

August 16, 2020 · 1 min · jiezi

关于chrome:CentOS-6-安装-Chrome最简单的方法

【转载请注明出处】:https://blog.csdn.net/huahao1989/article/details/107967581 明天有个共事说:“龙哥,我要在CentOS 6.5上装个Chrome,两天了,你帮我看看”。我一听这话头大呀,我记得N久之前我也是须要在CentOS 6.5上搞一个基于Chrome的爬虫,也是费了很大的劲,Chrome官网上早都提醒起码CentOS7了,装置一个依赖包的时候发现又须要另外一个依赖包,各种的依赖,特地吃力,起初找到了反对CentOS 6 的一个版本,才算是完满的解决了,明天也算是重走一遍,记录一下。 间接来个网盘 链接: https://pan.baidu.com/s/1zxbW... 提取码: ggyu先下载两个文件,而后执行上面的命令装置 rpm -i chrome-deps-stable-3.11-1.x86_64.rpmrpm -i --force --nodeps google-chrome-stable_current_x86_64.rpm如果不报错,那就祝贺你装置曾经实现。 个别状况下可能会提醒glibc版本低,那就降级 strings /lib64/libc.so.6 | grep GLIBC#先查看下曾经有的版本wget http://ftp.gnu.org/gnu/glibc/glibc-2.17.tar.gztar -zxvf glibc-2.17.tar.gzcd glibc-2.17mkdir buildcd build../configure --prefix=/usr --disable-profile --enable-add-ons --with-headers=/usr/include --with-binutils=/usr/bin make make install如果呈现 Can't open configuration file /usr/etc/ld.so.conf: No such file or directory输出: touch /usr/etc/ld.so.conf/etc/ld.so.conf sudo cp -r /etc/ld.so.c* /usr/etc/sudo ln -sf /usr/lib/libc-2.17.so /lib64/libc.so.6到这里要是执行任何命令都呈现 error while loading shared libraries: __vdso_time: invalid mode for dlopen(): Invalid argument那就执行上面命令先回退吧 ...

August 12, 2020 · 1 min · jiezi

关于chrome:你现在应该启用的10个超棒的Chrome功能

起源:公众号《前端全栈开发者》如果你能神奇地将你的浏览器降级为一般Chrome用户不晓得的性能,这不是很酷吗? 以下是十个Chrome性能,可帮忙你做到这一点。这些试验性功能,默认状况下尚未启用。 要启用这些性能,请查看chrome://flags。以下标记可能会在不久的未来正式公布。然而,截至撰写本文时,它们仍在测试中。 阅读器模式阅读器模式能够去除不必要的视觉凌乱,使浏览不受烦扰——当如此多的视觉元素抢夺咱们的注意力时,这一点十分重要。噗,不见了。 聚焦模式聚焦模式在新的框架窗口中关上标签,省略了标签条和搜寻栏,使界面更简洁。 天然型滚动动画重建其Edge平台后,Microsoft将其天然的滚动静止带到了Chromium。 标签组选项卡组用于将多个选项卡分组和治理在一起,例如用于不同类型的奶酪。 PDF双向视图PDF双向视图用于一次查看两页的PDF。乏味。 强制对网页内容应用暗模式这会迫使所有网站都出现深色主题,即便是没有主题的网站也是如此。 更宁静的告诉权限提醒这是一个简略的性能,能够缩小扰乱你流程的权限提醒。 标签悬停卡“Tab悬停卡”显示悬停时的标签预览。当你关上了超过30个标签页并且不再浏览标签页题目时,它可能会派上用场。 通过二维码启用页面共享此Flags使你能够共享带有二维码的网页,以便轻松地将内容发送到手机。当然,它还带有超赞的Dino吉祥物。 留神:在撰写本文时,这仿佛仅在Chrome Canary上无效。 并行下载Chrome能够建设多个连贯,将单个文件分次下载,从而进步下载速度。

August 10, 2020 · 1 min · jiezi

关于chrome:你现在应该启用的10个超棒的Chrome功能

起源:公众号《前端全栈开发者》如果你能神奇地将你的浏览器降级为一般Chrome用户不晓得的性能,这不是很酷吗? 以下是十个Chrome性能,可帮忙你做到这一点。这些试验性功能,默认状况下尚未启用。 要启用这些性能,请查看chrome://flags。以下标记可能会在不久的未来正式公布。然而,截至撰写本文时,它们仍在测试中。 阅读器模式阅读器模式能够去除不必要的视觉凌乱,使浏览不受烦扰——当如此多的视觉元素抢夺咱们的注意力时,这一点十分重要。噗,不见了。 聚焦模式聚焦模式在新的框架窗口中关上标签,省略了标签条和搜寻栏,使界面更简洁。 天然型滚动动画重建其Edge平台后,Microsoft将其天然的滚动静止带到了Chromium。 标签组选项卡组用于将多个选项卡分组和治理在一起,例如用于不同类型的奶酪。 PDF双向视图PDF双向视图用于一次查看两页的PDF。乏味。 强制对网页内容应用暗模式这会迫使所有网站都出现深色主题,即便是没有主题的网站也是如此。 更宁静的告诉权限提醒这是一个简略的性能,能够缩小扰乱你流程的权限提醒。 标签悬停卡“Tab悬停卡”显示悬停时的标签预览。当你关上了超过30个标签页并且不再浏览标签页题目时,它可能会派上用场。 通过二维码启用页面共享此Flags使你能够共享带有二维码的网页,以便轻松地将内容发送到手机。当然,它还带有超赞的Dino吉祥物。 留神:在撰写本文时,这仿佛仅在Chrome Canary上无效。 并行下载Chrome能够建设多个连贯,将单个文件分次下载,从而进步下载速度。

August 10, 2020 · 1 min · jiezi

关于chrome:十大相见恨晚的Chrome插件

(一)WEB前端助手(FeHelper)FeHelper几乎就是前端开发人员的神器,它是由国人开发的一款前端工具汇合的小插件,插件功能齐全,基本上涵盖了前端从业者常常会应用到的根底性能,应用起来也很棘手。上面就来感受一下弱小的性能: FE反对按需装置,也就是说,下面的这些性能, 你须要什用到什么再装置就行, 上面就挑两个我工作中应用到的: json 格式化 页面取色 咱们在开发时须要对一些内容进行取色, 很多小伙伴都是关上chrome调试器再应用取色器进行取色。应用FeHelper的取色器更加不便 JS正则表达式验证 不仅能够生成罕用的正则表达式, 也可能够校验表达式是否匹配, 在正则调试过程中能够起到较好地辅助作用 (二)vue-devtoolsvue-devtools是一款基于chrome游览器的插件,用于调试vue利用,被称为“Vue 调试神奇” vue是数据驱动的, 利用这个插件,这样就能看到vue中每个组件的data、props、computed等多种属性和办法,为咱们我的项目的开发与调试提供了很多的便当 。 (三)React Developer Tools如果你应用React进行开发,那必不可少的就是React Developer Tools, 它是Fecebook出品的,同样应用 React Developer Tools 进行调试时,能够查看应用程序的 React 组件分层构造,而不是更加神秘的浏览器 DOM 示意 (四)PostmanPostman 插件能够复用浏览器的Cookie,更加不便测试。不管你是做后端开发还是客户端开发,Postman都是测试HTTP接口的必备利器,反对集成测试;还能够将测试申请分组,而后批量执行。 (五)Octotree在GitHub边侧栏上显示代码树。非常适合查看我的项目源代码,无需将代码库clone到编辑器就能够如同在编辑器中操作一样, 能够间接搜寻文件跳转。 (六)Lighthouse 前端性能优化测试工具在前端开发中,对于本人开发的app或者web page性能的好坏,始终是让前端开发很在意的话题。咱们须要业余的网站测试工具,让咱们晓得本人的网页还有哪些须要更为优化的方面,我是应用过的一款工具:Lighthouse ,感觉还不错,记录下来,也顺便分享给用得着的搭档。 lighthouse 插件会对网页的各个测试项的后果打分,并给出优化倡议报告,是一个十分实用的可视化网站优化工具。 (七)Clear Cacheclear cache通过单击一个按钮革除缓存和浏览数据。应用此扩大疾速革除缓存,无需任何确认对话框,弹出窗口或其余懊恼。点击图标即可革除缓存、cookie等,开发必备!能够依据须要革除的数据定制ClearCache,这些数据包含利用缓存,Cookie,下载,文件系统,表单数据,历史记录,索引数据库,本地存储,插件数据,明码和WebSQL等。 (八) VimiumVimium 则继承了 Vim 中的罕用键位,让你在应用 Chrome 的过程中,无论是浏览网页、切换标签或是其它任何操作,全都能够只通过键盘实现。想像一下,你再也不须要挪动鼠标去关上一个链接,手指不必来到键盘,一切都是这么晦涩。 (九) Save All Resources当咱们在网页上看到炫酷的动画成果,一个很天然的想法就是F12, 而后下载资源,然而在chrome开发者工具中Source是找到以后页面所应用的资源,而咱们心愿能够间接一键下载所有网页资源,并且能够放弃目录构造。 一键下载网页资源(Save All Resources),能够完满的满足咱们的需要 ...

August 10, 2020 · 1 min · jiezi

关于chrome:CentOS-6x-搭建Headless-Chrome-ChromeDriver-Selenium的爬虫环境

【转载请注明出处】:https://blog.csdn.net/huahao1989/article/details/107890747 Chrome官方网站曾经说的很分明,不再反对6.x的CentOS,至多7以上。 可是很多时候咱们应用的服务器版本并不能轻易降级,即使曾经很好受了,然而还得持续应用低版本,装起来那是真叫一个吃力,还好就是吃力一些,最终还是能够装胜利的。 什么是 Headless ChromeHeadless Chrome 是 Chrome 浏览器的无界面状态,能够在不关上浏览器的前提下,应用所有 Chrome 反对的个性运行你的程序。相比于古代浏览器,Headless Chrome 更加不便测试 web 利用,取得网站的截图,做爬虫抓取信息等。相比于出道较早的 PhantomJS,SlimerJS 等,Headless Chrome 则更加贴近浏览器环境。 CentOS版本lsb_release -a 最新版本Google-Chrome装置CentOS/RedHat 7以上装置google-chrome能够齐全参考https://intoli.com/blog/insta... (6及以下版本不实用)。 指定yum源服务器应该指定适合yum源,防止找不到某些依赖的难堪。 批改 /etc/yum.repos.d/CentOS-Base.repo,能够应用阿里的yum repo: wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repoyum clean all装置google-chrome依据https://intoli.com/blog/insta... ,执行命令: curl https://intoli.com/install-google-chrome.sh | bash脚本会自动检测以后版本装置chrome所缺失的依赖包并下载。 查看是否还不足依赖: ldd /opt/google/chrome/chrome | grep "not found"返回为空,阐明CentOS下chrome依赖问题根本解决。 运行chrome执行 google-chrome-stable --no-sandbox --headless --disable-gpu --screenshot https://www.suning.com/。拜访胜利,在当前目录会生成截图screenshot.png,如果报错 [0100/000000.311368:ERROR:broker_posix.cc(43)] Invalid node channel message则须要装置依赖包: yum install \ ipa-gothic-fonts \ xorg-x11-fonts-100dpi \ xorg-x11-fonts-75dpi \ xorg-x11-utils \ xorg-x11-fonts-cyrillic \ xorg-x11-fonts-Type1 \ xorg-x11-fonts-misc -y 最新版本Chromedriver装置以后的chrome版本是 google-chrome-stable-72.0.3626.109-1.x86_64,chromedrive的官网是https://sites.google.com/a/ch...下载地址https://chromedriver.storage....或者抉择taobao镜像下载http://npm.taobao.org/mirrors...镜像下载地址http://npm.taobao.org/mirrors... ...

August 9, 2020 · 2 min · jiezi

关于chrome:CentOS-6x-搭建Headless-Chrome-ChromeDriver-Selenium的爬虫环境

【转载请注明出处】:https://blog.csdn.net/huahao1989/article/details/107890747 Chrome官方网站曾经说的很分明,不再反对6.x的CentOS,至多7以上。 可是很多时候咱们应用的服务器版本并不能轻易降级,即使曾经很好受了,然而还得持续应用低版本,装起来那是真叫一个吃力,还好就是吃力一些,最终还是能够装胜利的。 什么是 Headless ChromeHeadless Chrome 是 Chrome 浏览器的无界面状态,能够在不关上浏览器的前提下,应用所有 Chrome 反对的个性运行你的程序。相比于古代浏览器,Headless Chrome 更加不便测试 web 利用,取得网站的截图,做爬虫抓取信息等。相比于出道较早的 PhantomJS,SlimerJS 等,Headless Chrome 则更加贴近浏览器环境。 CentOS版本lsb_release -a 最新版本Google-Chrome装置CentOS/RedHat 7以上装置google-chrome能够齐全参考https://intoli.com/blog/insta... (6及以下版本不实用)。 指定yum源服务器应该指定适合yum源,防止找不到某些依赖的难堪。 批改 /etc/yum.repos.d/CentOS-Base.repo,能够应用阿里的yum repo: wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repoyum clean all装置google-chrome依据https://intoli.com/blog/insta... ,执行命令: curl https://intoli.com/install-google-chrome.sh | bash脚本会自动检测以后版本装置chrome所缺失的依赖包并下载。 查看是否还不足依赖: ldd /opt/google/chrome/chrome | grep "not found"返回为空,阐明CentOS下chrome依赖问题根本解决。 运行chrome执行 google-chrome-stable --no-sandbox --headless --disable-gpu --screenshot https://www.suning.com/。拜访胜利,在当前目录会生成截图screenshot.png,如果报错 [0100/000000.311368:ERROR:broker_posix.cc(43)] Invalid node channel message则须要装置依赖包: yum install \ ipa-gothic-fonts \ xorg-x11-fonts-100dpi \ xorg-x11-fonts-75dpi \ xorg-x11-utils \ xorg-x11-fonts-cyrillic \ xorg-x11-fonts-Type1 \ xorg-x11-fonts-misc -y 最新版本Chromedriver装置以后的chrome版本是 google-chrome-stable-72.0.3626.109-1.x86_64,chromedrive的官网是https://sites.google.com/a/ch...下载地址https://chromedriver.storage....或者抉择taobao镜像下载http://npm.taobao.org/mirrors...镜像下载地址http://npm.taobao.org/mirrors... ...

August 9, 2020 · 2 min · jiezi