Система сборки и зависимостей Google Closure Library
В этой статье мы рассмотрим систему сборки и зависимостей Google Closure Library.
А также увидим, как применить ее к своему коду, даже если вместо Google Closure Library используется совсем другой фреймворк.
Система зависимостей Google Closure Library имеет два основных декларативных метода: goog.provide и goog.require .
В javascript-файлах при помощи goog.provide указывается, какие символы предоставляет этот файл.
Символ - это имя javascript-объекта, который тут же можно использовать. Например:
goog.provide('my.super.dom')
my.super.dom.createElement = function() { ... }
Как видите, здесь мы декларируем, что файл объявляет символ my.super.dom , и goog.provide тут же создает пустой объект, используя для этого код, наподобие следующего:
my = window.my || {}
my.super = my.super || {}
my.super.dom = my.super.dom || {}
Так что существующие объекты и свойства не перезаписываются.
При помощи goog.require указывается, какие символы нужны. Указывать require принято после provide для лучшей читабельности кода.
Например:
goog.provide('goog.Delay');
goog.provide('goog.async.Delay');
goog.require('goog.Disposable');
goog.require('goog.Timer');
Функция goog.require лишь декларирует требование объекта и проверяет его. Она также может подгрузить нужный файл, но только если найдет его во внутренней структуре зависимостей.
Для добавления информации о зависимостях используется функция goog.addDependency .
Эта функция для каждого файла перечисляет список символов, которые он дает (provide ) и которые требует (require ).
Например:
goog.addDependency('/tmp/my/bye.js', ['my.bye'], ['my.main']);
Этот вызов добавляет в структуру зависимостей информацию, что файл bye.js предоставляет символ my.bye и требует my.main .
После такого вызова можно смело использовать goog.require('my.bye') - библиотека подгрузит файл /tmp/my/bye.js .
C другой стороны, если информация не была добавлена при помощи goog.addDependency - вызов goog.require('my.bye') завершится с ошибкой.
Для символов, объявленных в Google Closure Library, зависимости хранятся в корневой директории библиотеки, в файле deps.js .
Для ваших собственных символов и файлов вы должны либо прописать зависимости goog.addDependency самостоятельно, либо использовать для этого скрипт calcdeps.py (см. далее).
Для автоматической сборки и генерации файла зависимостей из ваших модулей используется скрипт calcdeps.py , поставляемый вместе с библиотекой.
Для его запуска под Windows можно использовать ActivePython, под Linux/MacOS - обычный python.
Эта утилита получает три основные опции:
-i file.js
- входной javascript-файл, можно указать несколько
-p path/to/dir
- список путей
-o script/deps/list/compiled
- тип вывода
Например:
calcdeps.py -i hello.js -p /tmp/my -p /tmp/gc/closure-library -o script
В нашем примере /tmp/my - место, где хранятся файлы main.js, bye.js, hello.js , а /tmp/gc/closure-library - каталог с google closure library, которая взята из SVN.
Скрипт calcdeps.py делает следующие простые шаги:
- Рекурсивно проходит по всем директориям из списка
-p , находит все файлы с расширением .js
- Для каждого файла - регулярными выражениями выцепляет списки, что ему надо (
goog.require ) и что он дает (goog.provide ).
- В зависимости от типа вывода:
deps
- Выводит набор директив
goog.addDependency .
В нашем случае это будет длинная простыня:
// This file was autogenerated by calcdeps.py
goog.addDependency('/tmp/my/bye.js', ['my.bye'], ['my.main']);
goog.addDependency('/tmp/my/hello.js', ['my.hello'], ['my.main']);
goog.addDependency('/tmp/my/main.js', ['my.main'], []);
goog.addDependency('/tmp/gc/closure-library/alltests.js', [], []);
goog.addDependency('/tmp/gc/closure-library/closure/goog/base.js', [], []);
goog.addDependency('/tmp/gc/closure-library/closure/goog/deps.js', [], []);
goog.addDependency('/tmp/gc/closure-library/closure/goog/array/array.js', ['goog.array'], []);
// ...
Первые несколько зависимостей взяты из файлов bye.js, main.js, hello.js, а остальные - построены из файлов Google Closure Library.
Свой deps.js в Closure Library
Если вы используете Google Closure Library, то можете загружать новый файл в качестве deps.js вместо стандартного.
Для этого нужно установить флаг:
// до загрузки base.js
goog.global.CLOSURE_NO_DEPS=true
(base.js перестанет подгружать стандартный deps.js ) и загружать deps.js через отдельный тег <script> , либо формировать список зависимостей goog.addDependency каким-либо другим путем.
list
выводит список нужных файлов в порядке зависимостей.
В нашем случае:
/tmp/gc/closure-library/closure/goog/base.js
/tmp/my/main.js
hello.js
Других файлов для сборки не нужно.
script
собирает все входные файлы (-i ) и требуемые для них в один файл.
В нашем случае это будет javascript-файл следующего вида:
// Input 0
содержание файла closure-library/closure/goog/base.js
// Input 1
содержание файла main.js
// Input 2
содержание файла hello.js
compiled
Компилирует файл, полученный в результате сборки. При использовании этой опции обязательно указание флага --compiler_jar с путем до jar-файла с компилятором.
Кроме того, как правило, указываются и флаги компиляции. Чтобы вывести откомпилированный файл в o.js , вызовем calcdeps.py вот так:
calcdeps.py -i hello.js -p /tmp/my -p /tmp/gc/closure-library -o compiled \
--compiler_jar compiler.jar --compiler_flags "--js_output_file o.js"
Кавычки для передачи флагов компилятора должны быть двойными.
Обратите внимание - в результате компиляции не будет директив goog.provide/require . Это потому, что компилятор использует специальный проход для проверки зависимостей и удаления этих директив из итогового файла.
С другой стороны, после компиляции с обычным уровнем оптимизации в файле остается много лишнего. Если добавить экспорт какой-нибудь функции и указать флаг "--js_output_file o.js --compilation_level ADVANCED_OPTIMIZATIONS" , то почти вся base.js исчезнет. Таким образом, overhead от использования системы сборки google будет сведен к минимуму.
Вообще, никто не заставляет использовать Google Closure Library. Для использования системы зависимости хватит base.js .
Так как calcdeps.py основан на регэкспах, условные директивы provide/require не поддерживаются. Утилита выхватит из файла все provide/require без разбора блока и местоположения в файле.
У функции goog.require есть один недостаток. Если встроенные зависимости Google Closure Library она загружает автоматически, то для собственных символов такой возможности не предусмотрено: нужно для каждого символа/файла прописывать goog.addDependency .
Чтобы упростить процесс, мы немного расширим goog.require , добавив автоматический подхват символов.
Исходный вариант:
goog.require = function(rule) {
// if the object already exists we do not need do do anything
// TODO: ...
if (!COMPILED) {
// если объект уже есть - возврат
if (goog.getObjectByName(rule)) {
return;
}
// получить путь к файлу с символом rule
var path = goog.getPathFromDeps_(rule);
if (path) {
// _writeScripts пишет <script> только 1 раз для каждого файла
goog.included_[path] = true;
goog.writeScripts_();
} else {
// файл не нашли
var errorMessage = 'goog.require could not find: ' + rule;
if (goog.global.console) {
goog.global.console['error'](errorMessage);
}
throw Error(errorMessage);
}
}
};
Введем правило - символ a.b.c находится в файле a/b/c.js , и модифицируем функцию goog.require , чтобы она при отсутствии зависимости в списке загружала файл по этому правилу.
А чтобы было еще удобнее - добавим префиксы, которые будут указывать путь к каждому пространству имен. Например:
goog.namespacePrefixes = {
'my': '/js/my'
}
Это будет означать, что goog.require('my.file') загрузит символ из /js/my/file.js .
Вот версия goog.require с соответствующими модификациями:
goog.require = function(rule) {
if (!COMPILED) {
if (goog.getObjectByName(rule)) {
return;
}
var path = goog.getPathFromDeps_(rule);
if (path) {
goog.included_[path] = true;
} else {
path = rule.replace(/\./g,'/')+'.js'
for(var prefix in goog.namespacePrefixes) {
path = path.replace(new RegExp("^"+prefix), goog.namespacePrefixes[prefix])
}
goog.included_[path] = true;
setTimeout(function() {
if (goog.getObjectByName(rule)) {
return
}
var errorMessage = 'goog.require could not find: ' + rule;
if (goog.global.console) {
goog.global.console['error'](errorMessage);
}
throw Error(errorMessage);
}, 0)
}
goog.writeScripts_();
}
};
В функции выше также оставлен контроль ошибок. В отличие от простого require , мы можем узнать, появился ли символ, только после загрузки файла, поэтому проверка обернута в setTimeout(..., 0) . Такой вызов сработает сразу после синхронной загрузки script .
Вы можете пропатчить base.js или, что гораздо лучше, загрузить свой файл с новым require и префиксами, который перезапишет определение в base.js.
После этого goog.require начнет подгружать зависимости аналогично системе зависимостей в dojo toolkit и других фреймворках.
Можно расширить эту функциональность, добавить подгрузку вида goog.require('my.*'), более сложную логику нахождения файла по символу и т.п., но нужно ли?
При сборке нескольких модулей Google Closure Compiler проверяет зависимости require/provide , но при этом многомодульные сборки можно делать и без них, как описано в соответствующей статье.
Для удобства примеры в этой статье собраны в архив gbuild.zip.
Он содержит модифицированный require и иллюстрирует, как использовать систему сборки Google, даже если вы не используете Google Closure Library.
Содержимое:
goog
директория с base.js из Google Closure Library
my
директория с нашими js-файлами, base_require.js содержит модифицированный require
calcdeps.py
стандартный calcdeps.py из Google Closure Library
compiler.jar
стандартный Google Closure Compiler
compile.bat
файл для компиляции hello.js с ADVANCED оптимизациями и зависимостями
hello.html
файл-пример, использующий hello.js
|
Кто-то разбирался как подцепить Google Closure Compiler к Ant'у?
http://www.daveoncode.com/2009/11/23/automatically-compile-javascript-ap...
Статья просто супер. Буду рекомендовать ее всем своим знакомым. Спасибо!!!
да, наверно так и есть
Юзаю для этого steal из JavaScriptMVC.
Ихний сборщик нуждается в допиливании, но на выходе - удобная штука.
I felt very happy while reading this site. This was a really very informative site for me. I really liked it. This was really a cordial post. Thanks a lot!
tank trouble
The article is very easy to understand, detailed and meticulous! I had a lot of harvest after watching this article from you! I find it interesting, your article gave me a new perspective! I have read many other articles on the same topic, but your article convinced me! mapquest driving directions
I just couldn't leave your website before telling you that I truly enjoyed the top quality info you present to your visitors? Will be back again frequently to check up on new posts.
rico chandra kusuma
i read a lot of stuff and i found that the way of writing to clearifing that exactly want to say was very good so i am impressed and ilike to come again in future..
divorce lawyers colorado springs
I am happy to find your distinguished way of writing the post. Now you make it easy for me to understand and implement the concept. Thank you for the post.
read the article
i read a lot of stuff and i found that the way of writing to clearifing that exactly want to say was very good so i am impressed and ilike to come again in future..
https://sportstv.io/en/watch-live/all-sports/upcoming
I'm glad I found this web site, I couldn't find any knowledge on this matter prior to.Also operate a site and if you are ever interested in doing some visitor writing for me if possible feel free to let me know, i am always look for people to check out my web site.
death cleanup
Wonderful article, thanks for putting this together! This is obviously one great post. Thanks for the valuable information and insights you have so provided here.
salehoo review
This article gives the light in which we can observe the reality. This is very nice one and gives indepth information. Thanks for this nice article.
psicoterapia en Madrid para adolescentes
The information is very special, I will have to follow you, the information you bring is very real, reflecting correctly and objectively, it is very useful for society to grow together
Very nice article, I enjoyed reading your post, very nice share, I want to twit this to my followers. Thanks!.
Webtalk app
i read a lot of stuff and i found that the way of writing to clearifing that exactly want to say was very good so i am impressed and ilike to come again in future..
結婚指輪 福岡
Nice to be visiting your blog once more, it has been months for me. Well this article that ive been waited for therefore long. i want this article to finish my assignment within the faculty, and it has same topic together with your article. Thanks, nice share.
fashion jewelry
Awesome and interesting article. Great things you've always shared with us. Thanks. Just continue composing this kind of post.
結婚指輪 猫
Thanks for another wonderful post. Where else could anybody get that type of info in such an ideal way of writing?
ハワイアンジュエリー
Great post, you have pointed out some fantastic points , I likewise think this s a very wonderful website.
結婚指輪 福岡
That is the excellent mindset, nonetheless is just not help to make every sence whatsoever preaching about that mather. Virtually any method many thanks in addition to i had endeavor to promote your own article in to delicius nevertheless it is apparently a dilemma using your information sites can you please recheck the idea. thanks once more.
ivo ignatov
It is wonderful to be here with everyone, I have a lot of knowledge from what you share, to say thank you, the information and knowledge here helps me a lot run 3
I would like to say that Elmhurst dentist blog really convinced me to do it! Thanks, very good post.
post free ads
This is a great thing, I think everyone feels this information is very valuable, thank you happy wheels
Спасибо за эту информацию!
Good post, thanks!
https://cofacerating.fr/avis-lhypnose-lauto-hypnose-perdre-poids.coface
Wow the blog you give us is amazing, no wonder many people want to read this. https://celebrityinsider.org/
I will recomend this blog to all of my friends. Great article.
https://happygamer.com/
Thank you for this inspiring blog. I wait for more
https://ballstepded.com/
I learned so much from this blog. Good inforamtion. https://fixoserror.com/
I wait for more.Great article.
https://premiereretail.com
I stumbled across this blog.Great article. https://tecsprint.com
Thank you for this amazing blog. Congratulations.
https://howtolose10poundsinaweek.com
The things i see here are very informative. Keep going. https://bargainistafashionista.com
I can say that is one of the best articles out on the internet. https://bankncard.com
I readed all the article. So informative https://vhan.net
This is one of the best sites i have found on the internet until now. Nice article keep going. https://millikenconstructioninc.com/
Thanks for the information, very clear and simple. I will try to use it.Love the way you write. Working my way through your article links
https://vvhen.to/
This is one of the best articles i found on the blogs around the internet. I am really interested in seeing more of this. Keep going with the great work!
https://gzgjskpzz1m.ga
First of all ,you have picked a very unique theme . I think i might design something similar for a future project that i want to build .
On top of that ,i in truth enjoy most of your content pieces and your different point of view.
Thank you https://seoconsultants24.blogspot.com/
Nice information, many thanks to the author. It is incomprehensible to me now, but in general, the usefulness and significance is overwhelming.https://seokarma24.blogspot.com/
I have reviewed the article many times and I find it very impressive. The information is extremely useful especially the last part I care about that information very much. I have been looking for this certain information for a long time.
https://packseo.blogspot.com/
I’m gone to tell my little brother, that he should
also pay a quick visit this blog on regular basis to take updated from hottest information.
https://connectorseo.blogspot.com/
You have made some really good points there. I looked on the web to find out
more about the issue and found most individuals will go along with your views on this website
https://digitalseo24h.blogspot.com/
Fantastic blog! Do you have any helpful hints for aspiring writers?
I’m hoping to start my own site soon but I’m a little lost on everything.
https://sweetseo24h.blogspot.com/
I am hoping the same best effort from you in the future as well. In fact your creative writing skills has inspired me.
https://fancyseo24h.blogspot.com/
You have made some really good points there. I looked on the web to find out
more about the issue and found most individuals will go along with your views on this website
https://phoenixseogeek.com/
Nice information, many thanks to the author. It is incomprehensible to me now, but in general, the usefulness and significance is overwhelming.
https://zgjskpzz1m.ga/
This is just the information I am finding everywhere. Thanks for your blog, I just subscribe your blog. This is a nice blog..
ที่เที่ยวพังงา
Thanks for sharing the information I find it really useful catalogos price shoes
I’d ought to seek advice from you here.
Which isn’t some thing Which i do! I enjoy reading an article which will make people believe.
Also, thanks for allowing me to comment! 먹튀검증
very nice post, i certainly love this fabulous website, go on it 대출
Your post content is being interested by a lot of people, I am very impressed with your post. I hope to receive more good articles. paper io 2
This is a great post!I didn't overdo it because of the inflated content 안전한놀이터, and I feel that I tried to keep the reader from 안전놀이터 feeling the burden with concise content.
Hello, I am one of the most impressed people 안전놀이터 in your article. I'm very curious about how you write such a good article. Are you an expert on this subject? I think so. I'm also very interested in this topic. Just as your writing was interesting, I think you will also be interested in my writing. You can check my writing by 메이저놀이터.
From one day, I noticed that many people post a lot of articles related to 안전놀이터. Among them, I think your article is the best among them!!I read it really interestingly.As much as I find it interesting, I think you can be impressed with my 토토커뮤니티. My site name is 토토커뮤니티사이트. Please visit!!
I'm curious how you can find and upload the material I wanted 안전놀이터. Your material related to is perfect. Also, don't you want to get material related to 토토커뮤니티? We look forward to a lot of activities in the future. If you have time, please visit mysite 토토커뮤니티사이트.
First of all, thank you for letting me see this information. I think this article can give me a lot of inspiration. I would appreciate 안전놀이터 if you could post more good contents in the future.
This is highly information, crisp and clear. You have a way of writing compelling information that sparks much interest.
https://larkenequity.com/ https://larkenequity.com//
Wow very good post, please dont stop posting things like this because ie really enjoy this
https://hrma-llc.com/
https://hrma-llc.com/
You are a very persuasive writer. I can see this in your article. You have a way of writing compelling information that sparks much interest.
https://nuestropsicologoenmadrid.com/
https://nuestropsicologoenmadrid.com/
I wish more authors of this type of content Wow.!This is highly information, crisp and clear. You have a way of writing compelling information that sparks much interest.!!!
https://cremationconsultancy.com/ https://cremationconsultancy.com//
This is very educational content and written well for a change. It's nice to see that some people still understand how to write a quality post!
https://i-repaircenter.nl/
https://i-repaircenter.nl/
I really thank you for the valuable info on this great subject and look forward to more great posts. Thanks a lot for enjoying this beauty article with me.
https://zoekmachineservices.nl/
https://zoekmachineservices.nl/
I do not know what to say really what you share very well and useful to the community, I feel that it makes our community much more developed
https://hetonderdelenhuis-emmen.nl/ https://hetonderdelenhuis-emmen.nl/
This is very educational content and written well for a change. It's nice to see that some people still understand how to write a quality post!
https://casinoonline-bet.com/
https://casinoonline-bet.com/
Great post! I am actually getting ready to across this information, is very helpful my friend. Also great blog here with all of the valuable information you have. Keep up the good work you are doing here
https://restorationdoctorva.com/
https://restorationdoctorva.com/
You are a very persuasive writer. I can see this in your article. You have a way of writing compelling information that sparks much interest.
https://fixoserror.com/
https://fixoserror.com/
Wow very good post, please dont stop posting things like this because ie really enjoy this
https://vvhen.to/
https://vvhen.to/
You are a very persuasive writer. I can see this in your article. You have a way of writing compelling information that sparks much interest.
https://millikenconstructioninc.com/
https://millikenconstructioninc.com/
I high appreciate this post. It’s hard to find the good from the bad sometimes, but I think you’ve nailed it!
https://safetytechnology.com
https://safetytechnology.com
I loved your post so much I became a fan of you, promise that you will continue to share such good and knowledgeable posts even further, we will be waiting for your post thank you.
https://bestpestcontrolservices.com.au
https://bestpestcontrolservices.com.au
Thank you so much for sharing this great blog.Very inspiring and helpful too.Hope you continue to share more of your ideas.I will definitely love to read.
https://bargainistafashionista.com/
https://bargainistafashionista.com/
Your information was very useful to me. That's exactly what I've been looking for
https://howtolose10poundsinaweek.com/
https://howtolose10poundsinaweek.com/
This is very educational content and written well for a change. It's nice to see that some people still understand how to write a quality post.!
https://tecsprint.com/
https://tecsprint.com/
Excellent article. Very interesting to read. I really love to read such a nice article. Thanks! keep rocking.
https://premiereretail.com/
https://premiereretail.com/
The post is written in very a good manner and it contains many useful information for me.
https://happygamer.com/
https://happygamer.com/
Now with coronavirus is really interesting to read things liek this on the internet when you stay at home
https://closetsphoenix.com/
https://closetsphoenix.com/
Wow very good post, please dont stop posting things like this because ie really enjoy this
https://caboplatinum.com/
https://caboplatinum.com/
Thank you so much for sharing this great blog.Very inspiring and helpful too.Hope you continue to share more of your ideas.I will definitely love to read.
https://zacjohnson.com/
https://zacjohnson.com/
Excellent article. Very interesting to read. I really love to read such a nice article. Thanks! keep rocking.
https://blogreign.com/
https://blogreign.com/
The post is written in very a good manner and it contains many useful information for me.
https://blogging.org/
https:https://blogging.org/
Very inspiring and helpful
https://blogninja.com/
https://blogninja.com/
This is very educational content and written well for a change. It's nice to see that some people still understand how to write a quality post.!
https://phoenixseogeek.com/
https://phoenixseogeek.com/
Thank you for such a well written article. It’s full of insightful information and entertaining descriptions. Your point of view is the best among many.
https://extremevaporizers.com/
https://extremevaporizers.com/
this is really nice to read..informative post is very good to read..thanks a lot!
https://usemybee.com/
https://usemybee.com/
Thanks for taking the time to discuss this, I feel strongly that love and read more on this topic. If possible, such as gain knowledge, would you mind updating your blog with additional information? It is very useful for me.
read more
Now with coronavirus is really interesting to read things liek this on the internet when you stay at home
https://spacnetwork.com/
https://spacnetwork.com/
This is just the information I am finding everywhere. Thanks for your blog, I just subscribe your blog. This is a nice blog..
visit here
This live album is going to go down as one of the best live albums of all time in the entire world. I have never experienced this myself but this album makes me feel that I wish I had been there to soak all that music in and feel the vibe of the crowd. I feel like I missed out on a historic event by missing this live concert. I would have gone too if it were not for my education and training seminars on how to play that new roblox game called pc.game.
This is such a great resource that you are providing and you give it away for free. I love seeing websites that understand the value of providing a quality resource for free. It is the old what goes around comes around routine.
instagram Abonnenten kaufen bei abonnenten24.de
Thanks for the nice blog. It was very useful for me. I'm happy I found this blog. Thank you for sharing with us,I too always learn something new from your post.
iluminação controlo
I can see that you are an expert at your field! I am launching a website soon, and your information will be very useful for me.. Thanks for all your help and wishing you all the success in your business.
online marketing
Very interesting discussion glad that I came across such informative post. Keep up the good work friend
https://pestcontrolcanberraarea.com.au
https://pestcontrolcanberraarea.com.au
I do not know what to say really what you share very well and useful to the community, I feel that it makes our community much more developed
https:https://emergencydental247.com/ https://emergencydental247.com/o/
It’s hard to find the good from the bad sometimes, but I think you’ve nailed it!
audigitalsolutions.com
audigitalsolutions.com
Great website and the content you shared is very informational and useful.
https://microjobs24.de https://microjobs24.de
Great write-up, I am a big believer in commenting on blogs to inform the blog writers know that they’ve added something worthwhile to the world wide web!..
house clearance bridgend
Thanks for taking the time to discuss this, I feel strongly about it and love learning more on this topic.
removal companies hartlepool
I can see that you are an expert at your field! I am launching a website soon, and your information will be very useful for me.. Thanks for all your help and wishing you all the success in your business.
Hausautomation
Very nice article, I enjoyed reading your post, very nice share, I want to twit this to my followers. Thanks!.
tree surgeon colchester
It is wonderful to be here with everyone, I have a lot of knowledge from what you share, to say thank you, the information and https://audigitalsolutions.com/
https://audigitalsolutions.com/
I know your expertise on this. I must say we should have an online discussion on this. Writing only comments will close the discussion straight away! And will restrict the benefits from this information.
covid playa del carmen
Now with coronavirus is really interesting to read things liek this on the internet when you stay at home
https://plasticpalletsales.com
https://plasticpalletsales.com
I have bookmarked your blog, the articles are way better than other similar blogs.. thanks for a great blog!
https://megabonuscasino.nl/
https://megabonuscasino.nl/
I do not know what to say really what you share very well and useful to the community, I feel that it makes our community much more developed
https://vosairservices.com/
https://vosairservices.com/
Excellent article. Very interesting to read. I really love to read such a nice article. Thanks! keep rocking.
https://entutorado.com/
https://entutorado.com/
Your content is nothing short of brilliant in many ways. I think this is engaging and eye-opening material. Thank you so much for caring about your content and your readers.
best time to go to cozumel
Information was useful to me, I searched a lot about it jigsaw puzzle
You have a good point here!I totally agree with what you have said!!Thanks for sharing your views...hope more people will read this article!!!
آموزش سیستم هوشمند
Hey there, You have done a fantastic job. I will definitely digg it and personally recommend to my friends. I am confident they'll be benefited from this website.
https://atlanticflagpole.com
https://atlanticflagpole.com
I appreciate, lead to I found just what I used to be taking a look for. You've ended my four day lengthy hunt! God Bless you man. Have a nice day. Bye
https://gold4vanilla.com/
https://gold4vanilla.com/
Thanks for the nice blog. It was very useful for me. I'm happy I found this blog. Thank you for sharing with us,I too always learn something new from your post.
lelkiismeretes ügyvéd Debrecen
I really loved reading your blog. It was very well authored and easy to understand. Unlike other blogs I have read which are really not that good.Thanks alot!
uniós pályázatírás Debrecen
It is appropriate time to make a few plans for the future and it's time to be happy. I've learn this publish and if I may just I want to counsel you some attention-grabbing things or tips. Maybe you could write subsequent articles regarding this article. I wish to learn even more issues approximately it!
https://schmidtchristmasmarket.com/
https://schmidtchristmasmarket.com/
this is really nice to read..informative post is very good to read..thanks a lot!
smm provider panel
This is my first time visit here. From the tons of comments on your articles,I guess I am not only one having all the enjoyment right here!
cenote a tulum
Attractive component of content. I just stumbled upon your weblog and in accession capital to say that I acquire actually enjoyed account your weblog posts. Any way I will be subscribing in your feeds or even I achievement you get admission to consistently fast.
https://whispersandhoney.com/
https://whispersandhoney.com/
Thanks for taking the time to discuss this, I feel strongly about it and love learning more on this topic. If possible, as you gain expertise, would you mind updating your blog with more information? It is extremely helpful for me.
otomatisasi rumah
I can see that you are an expert at your field! I am launching a website soon, and your information will be very useful for me.. Thanks for all your help and wishing you all the success in your business.
mindenki által ismert ügyvéd Debrecen
Отправить комментарий
Приветствуются комментарии:Для остальных вопросов и обсуждений есть форум.