ããã«ã¡ã¯ãã¨ã³ã¸ãã¢ãªã³ã°ã°ã«ã¼ãã®ç¦æ (@fukubaya) ã§ãã
2019å¹´3æã«åãã¡ã®ãã¼ã ãæ å½ããã¹ãã¼ããã©ã³ãµã¤ãããªãã¥ã¼ã¢ã«ãã¾ããã ãªãã¥ã¼ã¢ã«ã«éãã¦ããã£ãããªã®ã§æ°ããæè¡ããã¬ã¼ã ã¯ã¼ã¯ãæ¡ç¨ãããã¨ãããã¨ã§ã詳ããã¡ã³ãã¼ã¯ãã¾ããã§ãããVue.jsã§ãªãã¥ã¼ã¢ã«ãããã¨ã«ãã¾ãã*1ã æ¬è¨äºã§ã¯ãVue.jsãã»ã¼åå¿è ã ãã®ãã¼ã ã§Vue.js製ããã¸ã§ã¯ãããªãªã¼ã¹ããã¾ã§ã«å¾ãããç¥è¦ãã¾ã¨ãã¾ãã ãã§ã«ããªããªä½¿ãããªãã¦ããæ¹ã«ã¯ç©è¶³ããªãã¨æãã¾ãããããããVue.jsãå§ããæ¹ã®åèã«ãªãã°å¹¸ãã§ãã
- ãµã¼ãã¹ã®æ¦è¦
- éçºç°å¢
- ããã¸ã§ã¯ãè¨å®
- Vue Router
- 便å©ã ã£ãã©ã¤ãã©ãª
- æ¤è¨ããã(ã¾ã )ãããªãã£ããã¨
- We are hiring!
ãµã¼ãã¹ã®æ¦è¦
ãªãã¥ã¼ã¢ã«å¯¾è±¡ã®ãm3.comã«ã³ãã¡ã¬ã³ã¹ãã¯ãä¼å¡ã®å»å¸«å士ã§å°éçãªæè¦äº¤æãããããã®æ²ç¤ºæ¿ã®ãããªãµã¼ãã¹ã§ããYahoo!ç¥æµè¢ã®ãããªãµã¼ãã¹ãæ³åãã¦ããã ããã°ã ãããåã£ã¦ãã¾ãã
ãªãã¥ã¼ã¢ã«åã®ã¹ãã¼ããã©ã³ãµã¤ãã¯ã主ã«jspã¨jQueryã§æ§æããã¦ãã¾ããã jspã«ãã¸ãã¯æ¬ä½ããã®ã¾ã¾åãè¾¼ã¾ããã¬ãã«ã®è¤éãã§ã¯ããã¾ããã§ãããã 表示å´ã®å¶å¾¡ã ãã§ãé·å¹´ã®éçºã§ãããªãã«è¤éã«ãªã£ã¦ãããæ©è½è¿½å ãé£ãããªã£ã¦ãã¾ããã
ä»åã®ãªãã¥ã¼ã¢ã«ã§ã¯ããã¼ã¿ã®ããã¨ãã¯ãã¹ã¦REST APIã«å¯ããSPAã§æ§æãããã¨ã«ãã¾ããã
éçºç°å¢
ããã¸ã§ã¯ãã®ç®¡çã¯Vue CLIã§
ä»ããå§ãããªãã°Vue CLIã§ããã¸ã§ã¯ããä½ãã®ããªã¹ã¹ã¡ã§ãã
# Vue CLIã®ã¤ã³ã¹ãã¼ã« % yarn global add @vue/cli
createã³ãã³ãã§ããã¸ã§ã¯ããä½æããã¨ã å¿ è¦ãªè¨å®ã対話çã«æ±ºããå¾ã¯å¿ è¦ãªpackageãè¨å®ãã¡ã¤ã«ã®ã¤ã³ã¹ãã¼ã«ã¾ã§é²ãã¦ããã¾ãã
# æ°è¦appã®ä½æ % vue create new-app ...
Chromeã®æ©è½æ¡å¼µ Vue.js devtoolsã¯å¿ é
åã³ã³ãã¼ãã³ãã®dataãpropsã ãã§ãªããVuex ã Vue Routerã®ç¶æ ã¾ã§è¡¨ç¤ºã§ãã¾ãã ãã©ã¦ã¶ããæåã§dataãæ¸ãæãã¦åä½ã確èªãããã¨ãã§ãã¾ããéçºå¹çãä½åãéãã¾ãã
ãã³ãã«ãµã¤ãºã®ç¢ºèªã¯vue uiã§
Vue CLIã¯GUI(ã¦ã§ããã©ã¦ã¶)ã§ãæä½ã§ãã¾ãã
# localhostã§ãµã¼ããèµ·å % vue ui
以åã¯å¥ã®ãã¼ã«ãå ¥ããªãã¨ãã³ãã«ãµã¤ãºãªã©ã¯ç¢ºèªã§ãã¾ããã§ãããã ä»ã¯GUIããè¦è¦çã«ç¢ºèªã§ãã¾ãã
Storybookã¯ãã¶ã¤ãã¼ããããããã
Storybookã¯Vue.jsã ãã§ãªãReactãAngularã§UIã³ã³ãã¼ãã³ããéçºããããã®ãã¼ã«ã§ãã
# Vue CLIã§ã¤ã³ã¹ãã¼ã« % vue add storybook
åã³ã³ãã¼ãã³ããStorybookã«è¡¨ç¤ºãããæä½ããããã®ã³ã¼ããæ¸ãå¿ è¦ã¯ããã¾ããã ä¸æ¦æ¸ãã¦ãã¾ãã°ãã©ã¦ã¶ã§å®éã®è¡¨ç¤ºã確èªããªããã³ã³ãã¼ãã³ããéçºã§ãã¾ãã ãã©ã°ã¤ã³ãå ¥ããã¨viewportãå¤ãã£ãå ´åã®è¡¨ç¤ºãåãæ¿ãããã ã³ã³ãã¼ãã³ãã¸æ¸¡ãpropsãå¤ããå ´åã«ã©ã表示ãå¤ããããã¤ã³ã¿ã©ã¯ãã£ãã«ç¢ºèªã§ãã¾ãã
ãã¶ã¤ãã¼ããã¯åºæ¬çã«ã¯Storybookã¨ã³ã³ãã¼ãã³ãã ããè¦ãã°éçºãã§ãããã¨ãå¤ãã®ã§ã ãã¼ã«ã«ã§å¥éAPIãµã¼ããç«ã¡ä¸ãããããã¹ãç°å¢ã«ãã¡ãã¡å ¨é¨ããããã¤ããªãã¦ããã¶ã¤ã³ä½æ¥ãé²ãããã¾ãã åçãªé¨åã®è¡¨ç¤ºã®å¤åããã¶ã¤ãã¼ãããèªåã§è©¦ããã®ã§ã ã¨ã³ã¸ãã¢ã¯ã³ã³ãã¼ãã³ãã®templateã¨scriptãå®è£ ãã¦ããã°ãããç¨åº¦ãã¶ã¤ãã¼ããã«ãä»»ãã§ãã¾ãã ä¾ãã°ãæåæ°ãé·ãå ´åã®æãè¿ããã©ãè¦ããããç¹å®ã®æ¡ä»¶ã§ã ã表示ãããã¢ã¤ã³ã³ãæ£ããä½ç½®ã«ããããã¯Storybookä¸ã§ç¢ºèªã§ãã¾ãã
ããã¸ã§ã¯ãè¨å®
lintã¨èªåãã©ã¼ãããã¯å¿ é
Vue.jsã«éã£ããã¨ã§ã¯ãªãã§ããããã¼ã ã§éçºããä¸ã§lintã¨èªåãã©ã¼ãããã¯å¿ é ã§ãã ãã¯ã人éãæ°ã«ããã¹ãé åã§ã¯ããã¾ããã ãã©ã¼ããããçµ±ä¸ããã¦ããã°ãdiffãæ¬æ¥ããããå¤æ´ã ãã«ãªãã®ã§ãå·®åãåããããããªãã¾ãã ç¹ã«HTMLã¨CSSã¯æ¬æ¥ããããã£ãå¤æ´ä»¥å¤ã®ã¹ãã¼ã¹ãæ¹è¡ãå ¥ããããã®ã§ã ãã©ã¼ãããã¯åãããèªåã§å®æ½ããããã«ãã¦ããæ¹ãããã§ã*2ã
commitåã«ã¹ãã¼ã¸ã³ã°å¯¾è±¡ã®.jsã¨.vueã«lintã¨èªåãã©ã¼ããããå®è¡ããå度ã¹ãã¼ã¸ã³ã°ããè¨å®ãã¾ããã
package.json "gitHooks": { "pre-commit": "lint-staged" }, "lint-staged": { "*.{js,vue}": [ "vue-cli-service lint --fix", "git add" ] }
ãã¹ããæ¸ãã°ã³ã³ãã¼ãã³ãã¯é©åã«åå²ã§ãã
jspãçæãããã¼ã¸ãjQueryã§æä½ãããããªãã¼ã¸ã§ã¯ãDOMãjspã®å®è¡çµæã«ãã£ã¦ç¢ºå®ããã®ã§ã å®éã®DOMæ§é ã«åããããã¹ããä½ãã®ã¯ä¸å¯è½ã§ã¯ãªãã§ããå°é£ã§ããã Vue.jsã§ã¯ãã¼ã¸å ã®é¨åãã³ã³ãã¼ãã³ãåä½ã«åå²ããã¦ããã®ã§ã ä»ã®ã³ã³ãã¼ãã³ãã¨ã¯ç¬ç«ã«ãã¹ããå®è¡ãããã¨ãã§ãã¾ãã
éã«è¨ãã¨ãã³ã³ãã¼ãã³ãã¯ãã¹ããå®è¡ãããããããªåä½ã«åå²ããã¹ãã§ãã ãã¹ããæèããã¨ãã³ã³ãã¼ãã³ãã®è¨è¨ãèªç¶ã¨é©åãªå½¢ã«ãªãã¾ãã 巨大ãªã³ã³ãã¼ãã³ãã®ãã¹ããè¤éã«ãªãã®ã¯ãä»ã®è¨èªã¨åãã§ãã
// tests/unit/components/DialogModal.spec.js import DialogModal from "@/components/DialogModal.vue"; import { mount } from "@vue/test-utils"; describe("DialogModal", () => { it("should show okLabel and emit ok when clicked", () => { // DialogModalã³ã³ãã¼ãã³ãããã¦ã³ã // propsã® okLabel ã« "OK" ãæå® const wrapper = mount(DialogModal, { propsData: { okLabel: "OK" } }); // ãã¦ã³ãããã³ã³ãã¼ãã³ãå ã®buttonã¿ã°ãæ¢ãã¦ã¯ãªã㯠wrapper.find("button").trigger("click"); // buttonã¿ã°ã®ããã¹ãã "OK" ã«ãªã£ã¦ããã? expect(wrapper.find("button").text()).toBe("OK"); // ã³ã³ãã¼ãã³ããã "ok" ã¤ãã³ããéä¿¡ãããã expect(wrapper.emitted().ok).toBeTruthy(); // ã³ã³ãã¼ãã³ãããéä¿¡ããã "ok" ã¤ãã³ãã¯1åã ãã ã£ãã expect(wrapper.emitted().ok.length).toBe(1); }); });
注æãã¹ããªã®ã¯ãã³ã³ãã¼ãã³ãã®DOMæ§é ãCSSã¯ã©ã¹ãå¤æ´ããã ãã§ã ãã¹ãã«å¤±æãã¦ãã¾ãå ´åããããã¨ã§ãã
expect( wrapper.find("div.someclass span.num").text() ).toBe("10");
ãã®ãããªæå®ããã¦ãã㨠someclass
ã®ååãå¤ãã£ãæã span
ããªããªã£ãæã«ãã¹ãã«å¤±æãã¾ãã
è¦ãç®ãç´ãã ãã§ãã£ã¦ããDOMæ§é ãCSSã¯ã©ã¹ãå¤æ´ãããã¨ã¯ããããã®ã§ããã¹ãã¯å¤±æãããããªãã¾ãã
DOMæ§é ãidãclassã«é ¼ããããã¹ãã§ä½¿ãããã ãã®attributeãç¨æãã¦ãããæå®ããã ã¨ããæ¹æ³ãããããã§ã*3ã
éçºãµã¼ãããå¥ã®APIãµã¼ãã«ãããã·ãã
yarn run serve
(vue-cli-service serve --port 8081
) ã§èµ·åã§ããdevServerã§
éçºä¸ã®vueããã¸ã§ã¯ããlocalhostã§èµ·åãããã¨ãã§ãã¾ããã
REST APIã®URLãæ¬çªã¨ãã¼ã«ã«ã®éçºãµã¼ãã§éã£ã¦ãã¾ããæ¬çªç°å¢ã®è¨å®ã§ã¯APIãµã¼ãã«æ¥ç¶ã§ãã¾ããã
devServerã«ãããã·è¨å®ã vue.config.js
ã«å
¥ããã¨ã
ãã¡ãã¡REST APIã®URLãåãæ¿ããå¿
è¦ããªããªãã¾ãã
module.exports = { devServer: { proxy: { "^/service/api": { target: "http://localhost:9000", ws: false, pathRewrite: { "^/service/api": "/api" } } } } };
ãã®è¨å®ã§ã¯devServerã® /service/api*
ã¸ã®ã¢ã¯ã»ã¹ã
http://localhost:9000/api*
ã¸ãããã·ããã¾ãã
SpringBootã«çµã¿è¾¼ã
mvnã§ãã«ãããjarã«çµè¾¼ãããã«ããã¤ã vue.config.js
ã«è¨å®ãå
¥ãã¾ããã
cssãjsãªã©ã¯ static
以ä¸ã«ã index.html
ã sp-index.html
ã®ãã¡ã¤ã«åã§
templates
以ä¸ã«åºåãã¾ããã
module.exports = { ... outputDir: "src/main/resources/static/sp", indexPath: "src/main/templates/sp-index.html", ...
Controllerã®æ¹ã§ã¯ãã¢ã¯ã»ã¹ã®å¯è½æ§ã®ããpathã®ãã¿ã¼ã³ãVueRouterã®è¨å®ã¨åããã¦
ãã¹ã¦ sp-index.html
ã§åããããã«è¨å®ãã¾ããã
/
ã ãã 㨠VueRouterã§ã«ã¼ã«ãè¨å®ãã¦ãã¦ãã
ç´æ¥ã¢ã¯ã»ã¹ãæ¥ãæã« sp-index.html
ãèªã¾ããªãã®ã§è¡¨ç¤ºã§ãã¾ããã
@Controller @RequestMapping(value = "/sp") public class SpPageController { private static final String SP_INDEX_PATH = "sp-index"; @Autowired protected MessageService messageService; // VueRouterã®è¨å®ã¨åããã @RequestMapping(value = {"/", "/foo/**", "/bar/list/*", "/form/**"}, method = RequestMethod.GET) public String index(HttpServletRequest request) { return SP_INDEX_PATH; } }
Vue Router
path paramsã ããéããã¼ã¸éã§é·ç§»ãã¦ãcreated()ãmounted()ãå¼ã°ããªãã®ã§ãã¼ã¸å 容ãæ´æ°ãããªã
/contents/topic/12
ã®ããã«pathã«ãã©ã¡ã¼ã¿ãæããã¦ããå ´åãVue Routerã§ã¯
{ name: "topic", path: "/contents/topic/:topic_id", component: TopicView }
ã®ãããªè¨å®ããã訳ã§ããã /contents/topic/12
â /contents/topic/13
ã®ããã«
ãã¼ã¸é·ç§»ãã¦ã TopicView
ã® created()
ã mounted()
ãå度å¼ã°ãããã¨ã¯ããã¾ããã
åã TopicView
ã§ã®é·ç§»ãªã®ã§ãã®ã³ã³ãã¼ãã³ãã¯ãã®ã¾ã¾åå©ç¨ãããæ´æ°ããå¿
è¦ããªãããã§ãã
created()
ã mounted()
ã«ã ãAPIããã³ã³ãã³ããèªã¿è¾¼ãå¦çãæ¸ãã¦ãã¦ãã
ãã¼ã¸é·ç§»ããæã«æ°ãã«ã³ã³ãã³ãåå¾å¦çã¯å®è¡ããã¾ããã
Vue Routerã§ã¯ããã¼ã¸é·ç§»ã®ä¸é£ã®ããããã®ã¿ã¤ãã³ã°ã§å®è¡ããå¦çãè¨å®ããããã®ããã¯ãç¨æããã¦ãã¾ãã
ãã®ãã¡ãã³ã³ãã¼ãã³ãã¯åå©ç¨ããããã©å¥ã«ã¼ãã«é·ç§»ããæã«å¼ã°ããããã¯beforeRouteUpdate
ã§ã³ã³ãã³ããèªã¿è¾¼ãå¦çãå®è¡ãããã¨ã«ãã¾ããã
/** æåã«ã³ã³ãã¼ãã³ããä½ãããæã«å¼ã°ãã */ created() { this.initialize(); this.setupPage(this.$route); }, /** ã³ã³ãã¼ãã³ãã¯åå©ç¨ããã¦ãã«ã¼ãã ãå¤ããæã«å¼ã°ãã */ beforeRouteUpdate(to, from, next) { // toãé·ç§»å ãfromãé·ç§»å ã® $route this.initialize(); this.setupPage(to); // ç¶ãã®å¦çãå®è¡ next(); }, methods: { /** åæå(æåã«ã³ã³ãã¼ãã³ããèªã¾ããæããã¼ã¸å ¨ä½ãæ´æ°ããæã«å¼ã¶) */ initialize() { this.refresh(); }, /** dataãåæåãã */ refresh() { this.foo = {}; this.bar = {}; }, /** ã³ã³ãã³ãã®èªã¿è¾¼ã¿ */ setupPage(route) { // path parameterã使ã£ã¦ãã¼ã¿ãåå¾ const topicId = route.params.topic_id; this.foo = ApiClient.getFoo(topicId); this.bar = ApiClient.getBar(topicId); ... } }
表示æ©ä¼ãå°ãªããã¼ã¸ã¯é 延ãã¼ãããã¦ãã³ãã«ãµã¤ãºãå°ãããã
ãµã¼ãã¹å ã«ã¯ãã表示ããããã¼ã¸ã¨ãããã»ã©è¡¨ç¤ºãããªããã¼ã¸ãããã¾ãã æ稿ä¸è¦§ãã¼ã¸ã¯ãã表示ããã¾ãããåãåãããã©ã¼ã ã¯ã»ã¨ãã©è¡¨ç¤ºããã¾ããã
ç¹ã«æèããªãã§ãã«ãããã¨ããã表示ããããã¼ã¸ãããã§ãªããã¼ã¸ãå ¨é¨ä¸ç·ã®ãã¡ã¤ã«ã«ã¾ã¨ãããã¾ãã ä»®ã«ãåãåãããã©ã¼ã ã®ãã¡ã¤ã«ãµã¤ãºãå ¨ä½ã®ååãå ãã¦ãã¾ã£ã¦ãããã æ稿ä¸è¦§ãã¼ã¸ããè¦ãªãã¦ã¼ã¶ã¯æ¬æ¥å¿ è¦ãªãã¡ã¤ã«ã®2åã®ãµã¤ãºããã¦ã³ãã¼ããããã¨ã«ãªã£ã¦ãã¾ãã¾ãã
ã¹ãã¼ããã©ã³ãµã¤ããªã®ã§ããã¦ã³ãã¼ãããããµã¤ãºã¯å¯è½ãªéãå°ãããããã§ãã ããã§ã表示æ©ä¼ãå°ãªããã¼ã¸ã¯é 延ãã¼ãã£ã³ã°ããã¦ãã¡ã¤ã«ãåå²ãã ãã¦ã³ãã¼ããµã¤ãºãé©åã«ãªãããã«ãã¾ãã*4ã
// router/index.js // ããè¦ããããã¼ã¸ã¯ä¸æ¬import import TopicList from "@/views/TopicList.vue"; // ãã¾ãè¦ãããªããã¼ã¸ã¯é 延ãã¼ã const InquiryForm = () => import("@/views/InquiryForm.vue"); const router = Router({ ... routes: [ { name: "topicList", path: "/", component: TopicList }, { name: "inquiryForm", path: "/inquiry", component: Inquiryform } ] });
便å©ã ã£ãã©ã¤ãã©ãª
vue-content-loader
ã³ã³ãã³ãã®èªã¿è¾¼ã¿ä¸ã表示ãããã¹ãã³ã³ãã³ãã®ä»£æ¿ã¨ãã¦ä¸æçã«è¡¨ç¤ºããã¦ããã¢ã¬ãä½ãã¾ãã å®ä½ã¯SVGã®ã¢ãã¡ã¼ã·ã§ã³ã«ãªãã®ã§ãã¢ãã¡ã¼ã·ã§ã³GIFãªã©ãç¨æããªãã¦ãå®ç¾ã§ãã¾ãã ãªã³ã©ã¤ã³ã¨ãã£ã¿ ãGUIã§ã³ã³ãã¼ãã³ãã¾ã§çæã§ãã¦ä¾¿å©ã§ãã
vue-lazyload
ç»åã®é 延表示æ©è½ãçµè¾¼ã¿ã¾ããimgã¿ã°ã®attributeãã¡ãã£ã¨ç´ãã ãã§å°å ¥ã§ããã®ã§è¨ç½®ãç°¡åã§ãã
vue-scrollto
座æ¨ã ãã§ãªããç¹å®ã®ã³ã³ãã¼ãã³ããããä½ç½®ã§ã¹ã¯ãã¼ã«ä½ç½®ãæå®ã§ãã¾ãã
æ¤è¨ããã(ã¾ã )ãããªãã£ããã¨
TypeScriptã¯ã¾ã 使ããªã
éçºå½åãTypeScriptã§æ¸ããã¨ãæ¤è¨ãã¾ããããæçµçã«ã¯è¦éãã¾ããã ä¸çªã®çç±ã¯ãå種å¤é¨ã©ã¤ãã©ãªãå©ç¨ããã«ããã£ã¦ãããã¥ã¡ã³ããWebä¸ã®æ å ±ãã©ã¤ãã©ãªã«ãã£ã¦ã¯ ã¾ã æã£ã¦ããªãã¨æããããã§ãã VuexãVue Routerãªã©æåãªãã®ã¯ãµãã¼ããããã¥ã¡ã³ããã§ãã¤ã¤ããã¾ããã ãã¤ãã¼ãªãã®ã»ã©æ å ±ãè¦ã¤ããã試è¡é¯èª¤ã«æéãã¨ããããã ã¨å¤æãã¾ããã
ãã ãã²ã¨ã¨ããå®è£ ãçµãã£ãç¾å¨ã®èªèã¨ãã¦ã¯ããã¯ãåãããæ¹ãå®è£ ããã¹ãã®é¢ã§æå©*5ã§ãããã¨ã¯æç½ãªã®ã§ãã¿ã¤ãã³ã°ãã¿ã¦TypeScriptã¸ã®ç§»è¡ã¯å®æ½ãã¦ããããã§ãã
VeeValidateã¾ã 使ããªã
VeeValidate ã¨ããã¨ã¦ã便å©ãªValidation Frameworkãããã¾ãã
æ¬ãµã¼ãã¹ã§ã¯ãæ稿ãã©ã¼ã ã®ããªãã¼ã·ã§ã³ã«å½åå°å ¥ããã¤ããã§ããããéä¸ã§ããããã¨ã«ãã¦ãèªåã«ããªãã¼ã·ã§ã³ãå®è£ ãããã¨ã«ãã¾ããã
çç±ã¯ãã³ãã«ãµã¤ãºã®å¤§ããã§ããåç´ã«è¿½å ããã¨gzipã§ã30KBãããã«ãªãã¾ã*6ã å¿ è¦ãªã«ã¼ã«ã¨ã¨ã©ã¼ã¡ãã»ã¼ã¸ã®è¨èªãæå®ãããã¨ãã§ãã¾ãããããã§ã15KBãããã§ãã Vue.jsæ¬ä½ãé«ã 30KBãªã®ã§ããã¨åçã®ãµã¤ãºã«è¦åãå¿ è¦æ§ãæããªãã£ãã ããã«ããªãã¼ã·ã§ã³ãå¿ è¦ãªé ç®ãå¤ããªãã£ãã®ã§ä»åã¯è¦éãã¾ããã
åé¡ã¯ãã³ãã«ãµã¤ãºã ããªã®ã§ã社å ã§ä½¿ã管çç»é¢ã¨ããå ¥åé ç®ãå¤ããããªãã¼ã¸ã§ã¯ä½¿ã£ã¦ãããã¨æãã¾ãã ã¾ããå°æ¥çã«ã¯ããã«å°ããããè¨ç»ããã*7ãããªã®ã§ãå®è£ ããããã¹ãã¼ããã©ã³ãµã¤ãã§ãæ¡ç¨ããããããã¾ããã
We are hiring!
ãµã¼ãã¹æ¦è¦ã§ç´¹ä»ããããã«ãåãã¡ã®ãã¼ã ã§ã¯ãã¬ã¬ã·ã¼ãªãµã¼ãã¹ããããªãã«æ®ã£ã¦ãã¾ãã ãããããå¤ããã®ã¯ãªãã¥ã¼ã¢ã«ãã¦ããäºå®ãªã®ã§ã ããã³ãã«éããæ°ããæè¡ã§ã¬ã¬ã·ã¼ãµã¼ãã¹ãç½®ãæãã¦ããã仲éãåéä¸ã§ãã ãæ°è»½ã«ãåãåãããã ããã
*1:社å ã®å¥ãã¼ã ã«äºä¾ã¯ãã£ãã®ã§ææªãªãã¨ããªãã ãããã¨ããç®è«è¦ã¯ããã¾ããã
*2:HTMLã¿ã°ã®æ¹è¡ä½ç½®ãæ°æã¡æªãã§ããããã«æ £ãã¾ãã
*3:ããã§ããã¶ã¤ã³ä¿®æ£æã«ãã¶ã¤ãã¼ãããæ¶ãã¡ãã£ãããããã¨ã¯ããã¾ããã©ãã
*4:åå²ããããã¨ãµã¼ãã¸ã®ãªã¯ã¨ã¹ããå¢ãã¦ãã¾ã£ã¦ããã¯ããã§é ããªã£ã¦ãã¾ãã®ã§ãã©ãåå²ãããã¯ãµã¼ãã¹ã®å©ç¨ç¶æ³ãªã©ãåæ¡ãã¦æ±ºããã¹ãã§ã
*5:åããªãã¨ãã³ã¼ããå¤æ´ããæã«ãæ¢åãã¹ããééã£ã¦éã£ã¦ãã¾ãå¯è½æ§ãé«ãã¨æãã¾ããã
*6:https://baianat.github.io/vee-validate/concepts/bundle-size.html#minimal-bundle
*7:https://baianat.github.io/vee-validate/concepts/bundle-size.html#modular-approach