zoukankan      html  css  js  c++  java
  • Cesium深入浅出之webpack搭建框架

    引子

    一年前刚开始搞Cesium的时候还是使用的require.js进行模块封装,r.js进行打包,后面又用了gulp进行打包,但总感觉是不够智能。require.js自然不用说了,It's too old,gulp配置也太麻烦,也是这之后才玩的webpack,后知后觉的,原来还有这么智能的打包工具啊。用它来打包Cesium项目挺香,虽然你们都喜欢Vue+Cesium的组合,但我还是偏爱ES6+webpack,原生质感让我流连忘返。

    预期效果

    准备工作

    今天问了下群友有没有玩webpack+Cesium的,结果是没又几个人,基本都是Vue+Cesium,至于打包的工具嘛,好像现在又流行rullup。反正我是挺懵逼的,现在前端技术变化这么快吗,webpack我才刚玩溜,一度怀疑这篇文章还有没有继续写下去的必要了。后来想想还是有始有终吧,既然开了头就要完成它,况且我觉得webpack还能再战几年啊,我还是坚持用它吧,毕竟熟悉嘛。闲话不多说了,开始准备工作。

    新建项目

    因为我打算从零开始搭建基于webpack的Cesium开源平台,本篇做为平台第一篇,所以要从新建项目开始。关于IDE我是用IDEA,大家先不要开喷为啥你做前端的不用VSCODE,因为我是做后台出身的,而且后面也有可能要上后台的,所以一套IDEA搞定前后两端得了。

    1、IDEA中点击新建,选择Javascript类型项目,输入项目名称,选择创建好项目。我的项目名字叫simple-cesium,意为浅显易懂、简单易用的Cesium,符合深入浅出的理念。

    2、创建一个src文件夹来存放源码,创建一个css文件夹来存放样式表,创建一个public文件夹来存放静态文件。

    3、新建一个index.js文件放到src文件夹中,内容:

    console.log("Hello World!");

    新建一个index.html文件,标题为simple-cesium,放到public文件夹下,内容:

     1 <!DOCTYPE html>
     2 <html lang="en">
     3     <head>
     4         <meta charset="utf-8">
     5         <meta http-equiv="X-UA-Compatible" content="IE=edge">
     6         <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
     7         <title><%= htmlWebpackPlugin.options.title %></title>
     8     </head>
     9     <body>
    10         <noscript>
    11             <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript
    12                 enabled. Please enable it to continue.</strong>
    13         </noscript>
    14         <div id="cesiumContainer" class="cesiumContainer">
    15             <div id="cesiumSlider" class="cesiumSlider"></div>
    16             <div id="creditContainer" class="creditContainer"></div>
    17         </div>
    18         <!-- built files will be auto injected -->
    19     </body>
    20 </html>

    新建一个main.css文件,放到css文件夹中,内容:

    1 @charset "utf-8";
    2 html { height: 100%; overflow: hidden;}
    3 body { background: #000; color: #eee; font-family: sans-serif; font-size: 9pt; padding: 0; margin: 0; width: 100%; height: 100%; overflow: hidden;}
    4 
    5 .cesiumContainer { width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden; }
    6 .cesiumSlider { display: none; position: absolute; left: 50%; top: 0; background-color: rgba(210, 255, 255, .5); width: 4px; height: 100%; z-index: 1; }
    7 .cesiumSlider:hover { cursor: ew-resize; }
    8 .creditContainer { display: none; }

    4、创建package.json文件,后面的模块依赖会自动写入到这个文件中。 命令行输入:

    npm init

    填入相关信息,生成package配置如下:

     1 {
     2   "name": "simple-cesium",
     3   "version": "0.0.1",
     4   "dependencies": {},
     5   "devDependencies": {},
     6   "description": "Make the Cesium simple!",
     7   "main": "index.js",
     8   "scripts": {
     9     "test": "echo "Error: no test specified" && exit 1"
    10   },
    11   "keywords": [
    12     "Simple",
    13     "Cesium"
    14   ],
    15   "author": "Helsing",
    16   "license": "Apache-2.0"
    17 }

    5、新建webpack.config.js文件,内容:

    1 const config = {};
    2 module.exports = config;

    这样,一个空项目就建好了。目录结构如下:

    |- simple-cesium
      |- .idea
    |- css
    main.css |- node_modules
    |- public
    favicon.ico
    index.html |- src index.js index.html package.json webpack.config.js

    安装webpack

    在安装webpack之前需要先安装node.js,至于安装方法不赘述了,请自行查阅资料。我的nodenpm版本分别为10.16.1和6.9.0,这个是之前装好的,因为我觉得它们的版本对本项目影响不大,所以没更新到最新版本。

    Terminal中执行命令:

    npm -i webpack -D

    这样就将webpack安装到项目中了,如果要全局安装请使用-g参数。安装后,package.json文件发生了变化:

    1 {
    2   "name": "simple-cesium",
    3   "version": "0.0.1",
    4   "dependencies": {},
    5   "devDependencies": {
    6     "webpack": "^5.9.0"
    7   }
    8   ...
    9 }

    我们看到webpack已经被安装到开发依赖中了,版本是5.9.0,这里要说明的是,webpack最近的大版本升级4.0到5.0变化是巨大的,而且5.0现在还存在着很多BUG以及插件的适配问题,目前的生产环境暂时不推荐升级,我用的最新版本,踩坑是难免的。

    webpack在4.0以后都要安装webpack-cli,所以继续执行命令:

    npm i webpack-cli -D

    上述都是使用开发环境依赖安装,如须全局安装选择参数-g即可。现在去看看node_modules目录的下面,“全家桶”已装满,说明webpack算安装完成了。

    配置webpack

    我们都知道webpack之所以强大,和它的插件生态密不可分的,所以安装完webpack只是第一步,后面还要上很多的插件。

    1、webpack-dev-server,我认为这最重要的插件,开发调试之利器也。

    首先,安装webpack-dev-server,执行命令:

    npm i webpack-dev-server -D

    然后,配置一下package.json文件,在里面添加调试脚本:

    1 "scripts": {
    2   "test": "echo "Error: no test specified" && exit 1",
    3   "build": "cross-env NODE_ENV=production node_modules/.bin/webpack --progress --config webpack.config.js",
    4   "start": "cross-env NODE_ENV=development node_modules/.bin/webpack-dev-server --progress --config webpack.config.js --open chrome --hot"
    5 }

    生产模式下使用build,开发模式下使用start进行调试,open参数设置打开chrome浏览器,hot参数设置热更新。另外,上面出现了cross-env,它是一个可以运行跨平台设置和使用环境变量的插件,可以让你在Windows系统下使用process.env.NODE_ENV

    需要事先安装cross-env,执行命令:

    npm i cross-env -D

    最后,来配置下webapck.config.json文件:

     1 const config = {
     2     devServer: {
     3         hot: true, // 是否启用热更新。
     4         contentBase: path.join(__dirname, "dist"), // 告诉服务器从哪里提供内容。只有在你想要提供静态文件时才需要。
     5         // openPage: "index.html", // 指定打开的页面。指定路径会改变URL地址。
     6         compress: true, // 是否启用gzip压缩。
     7         port: 9999, // 端口号。
     8         lazy: false // 当启用lazy时,dev-server只有在请求时才编译包(bundle)。这意味着webpack不会监视任何文件改动。我们称之为“惰性模式”。
     9     }, // 开发调试工具
    10 }

    上述步骤完成后,启动start脚本调试项目,结果意料之中的抛出错误:

    error:Cannot find module 'webpack-cli/bin/config-yargs'

    上面说过了要踩坑的,这个算第一个吧。解决方法是改写package.json中的start脚本:

    "start": "cross-env NODE_ENV=development node_modules/.bin/webpack serve --progress --config webpack.config.js --open chrome --hot"

    可以看出,并不是webpack5.0不兼容webpack-dev-server了,而是调用方式发生了变化,现在是使用webpack serve的方式启动调试。

    安装Cesium

    常规的Cesium开发是直接下载编译好的库,然后使用标签或require方式进行全局引用,这种方式简单,不需要进行安装。但是这种方法没有办法将Cesium以模块方式重新打包,而我们这篇文章的目的就是在讲webpack与Cesium的结合,所以我们还要来安装一下Cesium,执行命令:

    npm i cesium -S 

    这里我们选择的是生产环境依赖安装,另外npm模块安装是区分大小写的,cesium首字母为小写,否则就是404了。

    配置Cesium

    在配置Cesium之前,我们先来完善一下webpack的基本配置:

     1 const config = {
     2     mode: nodeEnv, // 编译模式:"production" | "development" | "none"。
     3     context: __dirname, // 基础目录
     4     entry: {
     5         "simple-cesium": "./src/index.js"
     6     }, // 入口:string | object | array。这里应用程序开始执行,webpack开始打包。
     7     output: {
     8         filename: "[name].js", // 输出文件名:"[name].[hash:8].js", "bundle.js" | "[name].js" | "[chunkhash].js"。
     9         // publicPath: "/assets/", // 输出解析文件的目录,设置之后所有资源文件会自动加上这个路径,url地址是相对于HTML页面的。
    10         path: path.resolve(__dirname, "dist"), // path.join(__dirname,'dist'), // 输出路径,一般为绝对路径。
    11         chunkFilename: "[name].js", // 未被列入entry中,却又需要被打包出来的文件命名配置。
    12         library: "SimpleCesium", // 导出库的名称。
    13         libraryTarget: "umd" // 导出库的类型。常用umd模式,让输出的内容支持amd、commonJS模式加载。
    14     }, // 输出,webpack如何输出结果的相关选项。
    15     ...
    16 }

    各项参数含义请看注释,或到webpack的官网查阅。上述nodEnv变量为编译模式,需要自行要定义一下,path需要引用一下才能使用,如下:

    1 const path = require("path"); // 路径组件。
    2 const nodeEnv = process.env.NODE_ENV; // 编译模式。

    做完上述配置后,运行build脚本生成一下,发现dist目录下出现了simple-cesium.js文件,这说明项目已经成功生成了,但是一看大小才1KB,这明显没有把Cesium打包进来嘛。于是乎在index.js中添加Cesium引用:

    1 // import * as Cesium from "/node_modules/cesium/Source/Cesium.js";
    2 import Viewer from "/node_modules/cesium/Source/Widgets/Viewer/Viewer.js";

    我们先是直接引用Cesium的入口文件,引了这个文件基本就是把Cesium全家桶引进来了,然后运行build脚本,果不其然,3,055KB,这个大小可以用惊人来描述了。那么我们还是模块化引用吧,于是我们再引入Viewer,这个应该算是Cesium中的必备的Widget了吧,build,结果大小为2,683KB,这也没好哪里去嘛,只能说这个Viewer的家伙事儿也挺全的,但不管怎么样大小跟全家桶还是有区别的,所以我们还是坚持模块化引用吧。顺便要提一下,使用import引入的模块路径是否添加.js后缀是有区别的,webpack会把它们当成两个不同的模块,如果代码中刚好出现了用instanceof判断A是否为B的实例的时候,就会掉进坑里。我的习惯还是所有模块都加上.js后缀。

    到这里为止,我们已经能将Cesium和项目文件一起打包了,接下来的目标就是运行起Cesium的三维界面。

    为了动态引用JS脚本,我们要使用webpack-html-plugin插件,这个插件可以说是仅次于webpack-dev-server的存在,请看配置:

     1 plugins: [
     2     new HtmlWebpackPlugin({ // 打包输出HTML
     3         title: 'Simple Cesium', // 给模板中的html注入标题,需要在模板的html中指明配置,<%= htmlWebpackPlugin.options.title %>
     4         filename: 'index.html', // 指index定要生成的html路径,基于输出目录。
     5         template: 'public/index.html', // 指定html模板文件路径。这里的模板类型可以是任意你喜欢的模板,可以是 html、jade、ejs、hbs,等等,但是要注意的是,使用自定义的模板文件时,需要提前安装对应的loader,否则webpack不能正确解析。
     6         inject: 'body', // 注入选项。1.true:默认值,script标签位于html文件的body底部;2.body:script标签位于html文件的body底部(同true);3.head:script标签位于head标签内;4.false:不插入生成的js文件,只是单纯的生成一个html文件。
     7         favicon: 'public/favicon.ico', // 给生成的html文件生成一个favicon,属性值为favicon文件所在的路径名。
     8         hash: true, // 给生成的js文件一个独特的hash值,该hash值是该次webpack编译的hash值。默认值为false。
     9         cache: true, // 默认是true,表示内容变化的时候是否生成一个新的文件。
    10         showErrors: true, // 默认是true,作用是如果webpack编译出现错误,webpack会将错误信息包裹在一个pre标签内,属性的默认值为 true,也就是显示错误信息,开启这个方便定位错误。
    11         //chunks:['index','main'], // 主要用于多入口文件,当你有多个入口文件,编译后生成多个打包后的文件,那么chunks就能选择你要使用那些js文件,如果不设置则默认全部引入。
    12         //excludeChunks:['main.js'], // 排除掉一些js。
    13         minify: nodeEnv === 'production' ? { // 压缩html文件。属性值是一个压缩选项或者false。默认值为false,即不对生成的html文件进行压缩。
    14             caseSensitive: true, // 是否对大小写敏感,默认false。
    15             collapseBooleanAttributes: true, // 是否简写boolean格式的属性如:disabled="disabled" 简写为disabled  默认false。
    16             collapseWhitespace: true, // 是否删除空格与换行符,默认false。
    17             minifyCSS: true, // 是否压缩内联css(使用clean-css进行的压缩),默认值false。
    18             minifyJS: true, // 是否压缩html里的js(使用uglify-js进行的压缩)。
    19             preventAttributesEscaping: true, // 是否阻止属性值转义。
    20             removeAttributeQuotes: true, // 是否移除属性的引号,默认false。
    21             removeComments: true, // 是否删除注释,默认false。
    22             removeCommentsFromCDATA: true, // 是否从CDATA中删除注释,默认false。
    23             removeEmptyAttributes: true, // 是否删除空属性,默认false。
    24             removeOptionalTags: false, // 是否删除可选的标签,若开启此项,生成的html中没有body和head,html也未闭合。
    25             removeRedundantAttributes: true, // 是否删除多余的属性。
    26             removeScriptTypeAttributes: true, // 是否删除script的类型属性,在h5下面script的type默认值:text/javascript 默认值false。
    27             removeStyleLinkTypeAttributes: true, // 是否删除style的类型属性,type="text/css" 同上。
    28             useShortDoctype: true, // 是否使用短文档类型,默认false。
    29         } : {}
    30     })
    31     ...
    32 ],

    我这注释已经够详细了,相信已经不用多讲了。上述minify参数主要是用来做压缩的,可以选用默认设置或不设置,不用这么麻烦。

    接着我们再改造一下index.js,增加内容:

    const viewer = new Cesium.Viewer("cesiumContainer");

    如果使用模块方式引用的则改为如下写法:

    1 import Viewer from "/node_modules/cesium/Source/Widgets/Viewer/Viewer.js";
    2 const viewer = new Viewer("cesiumContainer");

    然后运行start脚本调试,页面并未正常显示,控制栏报错:DeveloperError: Unable to determine Cesium base URL automatically, try defining a global variable called CESIUM_BASE_URL。原来Cesium中有动态路径存在,使用webpack打包后CESIUM_BASE_URL的值就取不到了。这种动态路径的方式显然不符合webpack的模块式打包理念,但你又不能要求人家Cesium去改吧,所以只能自己改了。至于解决方法有以下几种:

    第一种,也是网上你能找到的最常见的解决方式,就是用DefinePlugin内置插件来重新定义CESIUM_BASE_URL的值。通常我们会把它定义为空,也就是默认的根路径,但如果你想更换别的路径,比如你想放到./libs目录下,那么你在用的时候也要把你打包后的文件放置在这个目录中,否则还是访问不到的。先说一下这种方式的具体做法吧,在webapck.config.js中的plugins配置中增加:

    1 plugins: [
    2     ...
    3     new webpack.DefinePlugin({
    4         CESIUM_BASE_URL: JSON.stringify("")
    5     })
    6 ],

    这里面用到了webapck的内置插件,因此先要引入webapck

    const webpack = require('webpack'); // 访问内置的插件

    这种做法很简单,唯一要注意的是字符串的值要使用JSON.stringify()来处理一下,否则是得不到预期的值的。

    第二种,替换Cesium中的获取动态路径的方法,这种方法比较繁琐,需要自定义插件,这里暂时不列出了。

    CESIUM_BASE_URL配置完成后,再运行页面,发现Cesium视窗已经能加载了,只是页面样式很乱,这是因为我们还未添加Cesium的内置CSS样式。添加样式引用:

    import "/node_modules/cesium/Source/Widgets/widgets.css"

    但是很不幸,又报错了:

    ERROR in ./node_modules/cesium/Source/Widgets/widgets.css 1:0
    Module parse failed: Unexpected character '@' (1:0)
    You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. 

    这说的是它不识别“@”字符?我也是懵逼的,但脑中第一反应是要装loader,果不其然,安装style-loadercss-loader之后解决问题。安装后要做如下配置:

    1 module: {
    2     rules: [
    3         ...
    4         {
    5             test: /.css$/i, // 正则表达式,表示.css后缀的文件。
    6             use: ['style-loader', 'css-loader'] // 针对css文件使用的loader,注意有先后顺序,数组项越靠后越先执行。
    7         }
    8     ]
    9 }

    这样应该就没问题了。不过如果你的css中引用了图片,最好配置一下url-loader,因为图片文件也是需要loader的。安装之后做一下配置:

     1 module: {
     2     rules: [
     3         ...
     4         {
     5             test: /.(png|jpg|jpeg|gif|svg)$/,
     6             loader: 'url-loader',
     7             options: {
     8                 name: './Assets/sc/[name].[ext]', // 这个路径其实是为了兼容Cesium的资源文件目录
     9                 limit: 10240 // 超过10K的不转换base64
    10             }
    11         }
    12     ]
    13 }

    已经胜利在望了,不过还没有结束,控制栏里仍然有好多404错误,这是因为Cesium的静态资源没有取到。上面我们讲过了CESIUM_BASE_URL的基本原理,知道Cesium的静态资源要放置于根目录下的,因此我们要把资源都拷贝过来,使用的插件是copy-webpack-plugin,配置如下:

    1 new CopyWebpackPlugin({
    2     patterns: [
    3         {from: path.join(cesiumSource, '../Build/Cesium/Workers'), to: 'Workers'},
    4         {from: path.join(cesiumSource, '../Build/Cesium/Assets'), to: 'Assets'},
    5         {from: path.join(cesiumSource, '../Build/Cesium/Widgets'), to: 'Widgets'},
    6         {from: path.join(cesiumSource, '../Build/Cesium/ThirdParty'), to: 'ThirdParty'}
    7     ]
    8 }), // 拷贝Cesium资源、控件、WebWorker到静态目录。

    大家请看上面的写法,跟你在网上看到的不一样,新版本的webpack请使用这里是新写法,否则报错哦。另外,最近的Cesium版本中增加了ThirdParty资源目录,某些高级应用中会使用到,因此也要将它拷贝过来。

    至此,Cesium+webpack的搭建工作应该算告一段落了。运行一下脚本,发现黑黑的夜空已经出现在眼前了,但是地球呢,去哪里了?

    首先,地球出不来的原因是影像数据没有正确加载,在没有指定影像数据的时候Cesium会默认从ION加载,而ION数据是需要token授权的。先去Cesium官网申请一个token,然后赋值。其次,还需要加载些3d模型,让地图更丰满些,我们可以直接加载Cesium的OSM城市模型。把index.js整体改造一下:

     1 import "/css/main.css";
     2 import "/node_modules/cesium/Source/Widgets/widgets.css";
     3 // import * as Cesium from "/node_modules/cesium/Source/Cesium.js";
     4 import Viewer from "/node_modules/cesium/Source/Widgets/Viewer/Viewer.js";
     5 import createOsmBuildings from "/node_modules/cesium/Source/Scene/createOsmBuildings.js";
     6 import Cartesian3 from "/node_modules/cesium/Source/Core/Cartesian3.js";
     7 import CesiumMath from "/node_modules/cesium/Source/Core/Math.js";
     8 import Ion from "/node_modules/cesium/Source/Core/Ion.js";
     9 
    10 const viewer = new Viewer("cesiumContainer", {
    11     creditContainer: "creditContainer"
    12 });
    13 viewer.scene.primitives.add(createOsmBuildings());
    14 viewer.scene.camera.flyTo({
    15     destination: Cartesian3.fromDegrees(-74.019, 40.6912, 750),
    16     orientation: {
    17         heading: CesiumMath.toRadians(20),
    18         pitch: CesiumMath.toRadians(-20),
    19     },
    20 });
    21 Ion.defaultAccessToken = 'Your Token';

    再次运行调试,就出现了纽约的城市模型,但是影像还是没出来,什么鬼?我也不知道是什么鬼,以前设置了token就可以了的。没办法,手工切换到OSM地图源,总算加载出来了。但是总不至于每次手动加载吧,那太麻烦了,于是乎我们来点自动化的:

    viewer.baseLayerPicker.viewModel.selectedImagery = viewer.baseLayerPicker.viewModel.imageryProviderViewModels[6];

    上述代码的意思让底图自动切换到第七个地图源,即OpenStreetMap。

    小结

    至此,Cesium+webpack平台搭建完成。后续可能会做一些诸如分包之类的优化工作,弄好了之后我会直接在这里更新,敬请关注!另外,小伙伴们有空可以来群854943530逛逛,一定不虚此行哦。

    -------------------- 不,这还不是我的底线 --------------------

    补充

    说好的后续优化来了。

    首先,来做个分包。分包种类很多,但我只喜欢简单粗暴的,就是分两个包,一个程序包一个运行时包,对应到本项目就是:simple-cesium.js和simple-cesium.runtime.js。程序包负责打包所有自写的代码,运行时包则是负责打包第三方库和一些通用库。这样做的目的是为了以最小的IO代价来进行版本更新,运行时包除非第三方库升级否则基本不会变动的,那么每次更新版本只需要更新程序包即可,所以我们把Cesium库也打包进运行时中。来看配置:

     1 optimization: {
     2     splitChunks: onePackage ? {} : {
     3         chunks: "initial", // 从哪些chunks里面抽取代码,还可以通过函数来过滤所需的chunks:"initial" | "async" | "all" | function。
     4         minSize: 30000, // 抽取出来的文件在压缩前的最小大小,默认为30000。
     5         maxSize: 0, // 抽取出来的文件在压缩前的最大大小,默认为0,表示不限制最大大小。
     6         minChunks: 1, // 被引用次数,默认为1。如common中minChunks为2,表示将被两次以上引用的代码抽离成common。
     7         maxAsyncRequests: 6, // 按需加载chunk的并发请求数量,默认为5。
     8         maxInitialRequests: 4, // 页面初始加载时的并发请求数量,默认为3。
     9         automaticNameDelimiter: '~', // 抽取出来的文件的自动生成名字的分割符,默认为~。
    10         cacheGroups: {
    11             vendor: {
    12                 name: "simple-cesium.runtime", // 抽取出来文件的名字,表示自动生成文件名。
    13                 test: /[\/](node_modules|thirdParty)[\/]/,
    14                 chunks: "all",
    15                 priority: 10 // 优先级。
    16             },
    17             common: {
    18                 name: "simple-cesium.common",
    19                 test: /[\/]src[\/]/,
    20                 minChunks: 2,
    21                 minSize: 0, // 如果被多次引用的通用代码文件不超过minSize,则不会被抽离。
    22                 chunks: "all",
    23                 priority: 15,
    24                 reuseExistingChunk: true
    25             }
    26         } // 缓存组。
    27     }
    28 }

     下面是打包后的目录:

    Cesium是个庞大的库,所以打包后的文件远不止这些,截图只截取了一部分。不过我还是有些疑问,相同的配置,我在另外一个webpack的项目中打包出来就两个文件,一个程序文件,一个运行时文件,也就是说所有的runtime都打包成一个文件了。于是网上苦寻答案,翻遍了竟然还是找不到究竟是哪个参数控制的,如果有大神知道,还请指点啊,毕竟运行时打包成一个文件也是有应用场景的。

    其次,就是自动清理dist文件夹,这个也是有必要的,Cesium每次大版本更新里面就会有大批文件变更,如果每次手动去清理就太麻烦了。可以使用clean-webpack-plugin来解决这个问题,安装后做如下配置:

    1 plugins: [
    2     new CleanWebpackPlugin(),
    3     ...
    4 ]

    这里要注意,它的引用方式也不一样:

    const {CleanWebpackPlugin} = require("clean-webpack-plugin");

    暂时就补充这两个吧,后续如果有别的优化还会继续补充的。

    最后,我把项目放到GitHub上了,后面我会以这个框架为起点继续深化的,感兴趣的小伙伴可以点个小星星持续关注一下哦。

  • 相关阅读:
    【LeetCode】048. Rotate Image
    【LeetCode】036. Valid Sudoku
    【LeetCode】060. Permutation Sequence
    【LeetCode】001. Two Sum
    【LeetCode】128. Longest Consecutive Sequence
    【LeetCode】081. Search in Rotated Sorted Array II
    【LeetCode】033. Search in Rotated Sorted Array
    顺时针打印矩阵
    矩形覆盖
    二维数组中的查找
  • 原文地址:https://www.cnblogs.com/HelsingWang/p/14065860.html
Copyright © 2011-2022 走看看