diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index a12930eea..6f3c1c087 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -1,15 +1,16 @@ module.exports = { + dest: 'vue-loader', locales: { '/': { + lang: 'zh-CN', + title: 'Vue Loader 中文文档', + description: '处理 Vue 单文件组件的 Webpack loader,Vue Loader 中文文档,Vue Loader 国内镜像,Vue Loader 中文网,Vue Loader 官网打不开,Vue Loader 官网打开慢' + }, + '/en': { lang: 'en-US', title: 'Vue Loader', description: 'Webpack loader for single-file Vue components' }, - '/zh/': { - lang: 'zh-CN', - title: 'Vue Loader', - description: '处理 Vue 单文件组件的 Webpack loader' - }, '/ru/': { lang: 'ru', title: 'Vue Loader', @@ -17,7 +18,7 @@ module.exports = { } }, serviceWorker: true, - theme: 'vue', + theme: 'docmirror', themeConfig: { algolia: { apiKey: '3462ea4a6a56b94eba5b01497d6eb627', @@ -29,7 +30,7 @@ module.exports = { updatePop: true }, locales: { - '/': { + '/en/': { label: 'English', selectText: 'Languages', editLinkText: 'Edit this page on GitHub', @@ -66,7 +67,7 @@ module.exports = { '/guide/testing' ] }, - '/zh/': { + '/': { label: '简体中文', selectText: '选择语言', editLinkText: '在 GitHub 上编辑此页', diff --git a/package.json b/package.json index 61f7e80fb..f28286860 100644 --- a/package.json +++ b/package.json @@ -94,7 +94,7 @@ "vue-server-renderer": "^2.5.16", "vue-template-compiler": "^2.5.16", "vuepress": "^0.14.2", - "vuepress-theme-vue": "^1.1.0", + "vuepress-theme-docmirror": "^1.1.1", "webpack": "^4.1.0", "webpack-cli": "^3.2.0", "webpack-dev-server": "^3.1.1", diff --git a/vue-loader/404.html b/vue-loader/404.html new file mode 100644 index 000000000..66465a920 --- /dev/null +++ b/vue-loader/404.html @@ -0,0 +1,17 @@ + + + + + + Vue Loader 中文文档 + + + + + + + +

404

That's a Four-Oh-Four.
Take me home.
+ + + diff --git a/vue-loader/_redirects b/vue-loader/_redirects new file mode 100644 index 000000000..07a2aff91 --- /dev/null +++ b/vue-loader/_redirects @@ -0,0 +1,13 @@ +# redirect v14 urls to root +/en/features/postcss.html /guide/pre-processors.html#postcss +/en/start/* /guide/:splat +/en/features/* /guide/:splat +/en/configurations/* /guide/:splat +/en/workflow/* /guide/:splat + +# redirect any other langs to legacy +/zh-cn/* https://vue-loader-v14.vuejs.org/zh-cn/:splat +/ja/* https://vue-loader-v14.vuejs.org/ja/:splat +/kr/* https://vue-loader-v14.vuejs.org/kr/:splat +/ru/* https://vue-loader-v14.vuejs.org/ru/:splat +/pt_BR/* https://vue-loader-v14.vuejs.org/pt_BR/:splat diff --git a/vue-loader/assets/css/0.styles.a8bea730.css b/vue-loader/assets/css/0.styles.a8bea730.css new file mode 100644 index 000000000..617403075 --- /dev/null +++ b/vue-loader/assets/css/0.styles.a8bea730.css @@ -0,0 +1 @@ +.home{padding:3.6rem 2rem 0;max-width:960px;margin:0 auto}.home .hero{text-align:center}.home .hero img{max-width:100%;max-height:280px;display:block;margin:3rem auto 1.5rem}.home .hero h1{font-size:3rem}.home .hero .action,.home .hero .description,.home .hero h1{margin:1.8rem auto}.home .hero .description{max-width:35rem;font-size:1.6rem;line-height:1.3;color:#6a8bad}.home .hero .action-button{display:inline-block;font-size:1.2rem;color:#fff;background-color:#3eaf7c;padding:.8rem 1.6rem;border-radius:4px;transition:background-color .1s ease;box-sizing:border-box;border-bottom:1px solid #389d70}.home .hero .action-button:hover{background-color:#4abf8a}.home .features{border-top:1px solid #eaecef;padding:1.2rem 0;margin-top:2.5rem;display:flex;flex-wrap:wrap;align-items:flex-start;align-content:stretch;justify-content:space-between}.home .feature{flex-grow:1;flex-basis:30%;max-width:30%}.home .feature h2{font-size:1.4rem;font-weight:500;border-bottom:none;padding-bottom:0;color:#3a5169}.home .feature p{color:#4e6e8e}.home .footer{padding:2.5rem;border-top:1px solid #eaecef;text-align:center;color:#4e6e8e}@media (max-width:719px){.home .features{flex-direction:column}.home .feature{max-width:100%;padding:0 2.5rem}}@media (max-width:419px){.home{padding-left:1.5rem;padding-right:1.5rem}.home .hero img{max-height:210px;margin:2rem auto 1.2rem}.home .hero h1{font-size:2rem}.home .hero .action,.home .hero .description,.home .hero h1{margin:1.2rem auto}.home .hero .description{font-size:1.2rem}.home .hero .action-button{font-size:1rem;padding:.6rem 1.2rem}.home .feature h2{font-size:1.25rem}}.searchbox{display:inline-block;position:relative;width:200px;height:32px!important;white-space:nowrap;box-sizing:border-box;visibility:visible!important}.searchbox .algolia-autocomplete{display:block;width:100%;height:100%}.searchbox__wrapper{width:100%;height:100%;z-index:999;position:relative}.searchbox__input{display:inline-block;box-sizing:border-box;transition:box-shadow .4s ease,background .4s ease;border:0;border-radius:16px;box-shadow:inset 0 0 0 1px #ccc;background:#fff!important;padding:0 26px 0 32px;width:100%;height:100%;vertical-align:middle;white-space:normal;font-size:12px;-webkit-appearance:none;-moz-appearance:none;appearance:none}.searchbox__input::-webkit-search-cancel-button,.searchbox__input::-webkit-search-decoration,.searchbox__input::-webkit-search-results-button,.searchbox__input::-webkit-search-results-decoration{display:none}.searchbox__input:hover{box-shadow:inset 0 0 0 1px #b3b3b3}.searchbox__input:active,.searchbox__input:focus{outline:0;box-shadow:inset 0 0 0 1px #aaa;background:#fff}.searchbox__input::-webkit-input-placeholder{color:#aaa}.searchbox__input:-ms-input-placeholder,.searchbox__input::-ms-input-placeholder{color:#aaa}.searchbox__input::-moz-placeholder{color:#aaa}.searchbox__input::placeholder{color:#aaa}.searchbox__submit{position:absolute;top:0;margin:0;border:0;border-radius:16px 0 0 16px;background-color:rgba(69,142,225,0);padding:0;width:32px;height:100%;vertical-align:middle;text-align:center;font-size:inherit;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;right:inherit;left:0}.searchbox__submit:before{display:inline-block;margin-right:-4px;height:100%;vertical-align:middle;content:""}.searchbox__submit:active,.searchbox__submit:hover{cursor:pointer}.searchbox__submit:focus{outline:0}.searchbox__submit svg{width:14px;height:14px;vertical-align:middle;fill:#6d7e96}.searchbox__reset{display:block;position:absolute;top:8px;right:8px;margin:0;border:0;background:none;cursor:pointer;padding:0;font-size:inherit;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;fill:rgba(0,0,0,.5)}.searchbox__reset.hide{display:none}.searchbox__reset:focus{outline:0}.searchbox__reset svg{display:block;margin:4px;width:8px;height:8px}.searchbox__input:valid~.searchbox__reset{display:block;-webkit-animation-name:sbx-reset-in;animation-name:sbx-reset-in;-webkit-animation-duration:.15s;animation-duration:.15s}@-webkit-keyframes sbx-reset-in{0%{-webkit-transform:translate3d(-20%,0,0);transform:translate3d(-20%,0,0);opacity:0}to{-webkit-transform:none;transform:none;opacity:1}}@keyframes sbx-reset-in{0%{-webkit-transform:translate3d(-20%,0,0);transform:translate3d(-20%,0,0);opacity:0}to{-webkit-transform:none;transform:none;opacity:1}}.algolia-autocomplete.algolia-autocomplete-right .ds-dropdown-menu{right:0!important;left:inherit!important}.algolia-autocomplete.algolia-autocomplete-right .ds-dropdown-menu:before{right:48px}.algolia-autocomplete.algolia-autocomplete-left .ds-dropdown-menu{left:0!important;right:inherit!important}.algolia-autocomplete.algolia-autocomplete-left .ds-dropdown-menu:before{left:48px}.algolia-autocomplete .ds-dropdown-menu{top:-6px;border-radius:4px;margin:6px 0 0;padding:0;text-align:left;height:auto;position:relative;background:transparent;border:none;z-index:999;max-width:600px;min-width:500px;box-shadow:0 1px 0 0 rgba(0,0,0,.2),0 2px 3px 0 rgba(0,0,0,.1)}.algolia-autocomplete .ds-dropdown-menu:before{display:block;position:absolute;content:"";width:14px;height:14px;background:#fff;z-index:1000;top:-7px;border-top:1px solid #d9d9d9;border-right:1px solid #d9d9d9;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);border-radius:2px}.algolia-autocomplete .ds-dropdown-menu .ds-suggestions{position:relative;z-index:1000;margin-top:8px}.algolia-autocomplete .ds-dropdown-menu .ds-suggestions a:hover{text-decoration:none}.algolia-autocomplete .ds-dropdown-menu .ds-suggestion{cursor:pointer}.algolia-autocomplete .ds-dropdown-menu .ds-suggestion.ds-cursor .algolia-docsearch-suggestion.suggestion-layout-simple,.algolia-autocomplete .ds-dropdown-menu .ds-suggestion.ds-cursor .algolia-docsearch-suggestion:not(.suggestion-layout-simple) .algolia-docsearch-suggestion--content{background-color:rgba(69,142,225,.05)}.algolia-autocomplete .ds-dropdown-menu [class^=ds-dataset-]{position:relative;border:1px solid #d9d9d9;background:#fff;border-radius:4px;overflow:auto;padding:0 8px 8px}.algolia-autocomplete .ds-dropdown-menu *{box-sizing:border-box}.algolia-autocomplete .algolia-docsearch-suggestion{display:block;position:relative;padding:0 8px;background:#fff;color:#02060c;overflow:hidden}.algolia-autocomplete .algolia-docsearch-suggestion--highlight{color:#174d8c;background:rgba(143,187,237,.1);padding:.1em .05em}.algolia-autocomplete .algolia-docsearch-suggestion--category-header .algolia-docsearch-suggestion--category-header-lvl0 .algolia-docsearch-suggestion--highlight,.algolia-autocomplete .algolia-docsearch-suggestion--category-header .algolia-docsearch-suggestion--category-header-lvl1 .algolia-docsearch-suggestion--highlight,.algolia-autocomplete .algolia-docsearch-suggestion--text .algolia-docsearch-suggestion--highlight{padding:0 0 1px;background:inherit;box-shadow:inset 0 -2px 0 0 rgba(69,142,225,.8);color:inherit}.algolia-autocomplete .algolia-docsearch-suggestion--content{display:block;float:right;width:70%;position:relative;padding:5.33333px 0 5.33333px 10.66667px;cursor:pointer}.algolia-autocomplete .algolia-docsearch-suggestion--content:before{content:"";position:absolute;display:block;top:0;height:100%;width:1px;background:#ddd;left:-1px}.algolia-autocomplete .algolia-docsearch-suggestion--category-header{position:relative;border-bottom:1px solid #ddd;display:none;margin-top:8px;padding:4px 0;font-size:1em;color:#33363d}.algolia-autocomplete .algolia-docsearch-suggestion--wrapper{width:100%;float:left;padding:8px 0 0}.algolia-autocomplete .algolia-docsearch-suggestion--subcategory-column{float:left;width:30%;text-align:right;position:relative;padding:5.33333px 10.66667px;color:#a4a7ae;font-size:.9em;word-wrap:break-word}.algolia-autocomplete .algolia-docsearch-suggestion--subcategory-column:before{content:"";position:absolute;display:block;top:0;height:100%;width:1px;background:#ddd;right:0}.algolia-autocomplete .algolia-docsearch-suggestion--subcategory-inline{display:none}.algolia-autocomplete .algolia-docsearch-suggestion--title{margin-bottom:4px;color:#02060c;font-size:.9em;font-weight:700}.algolia-autocomplete .algolia-docsearch-suggestion--text{display:block;line-height:1.2em;font-size:.85em;color:#63676d}.algolia-autocomplete .algolia-docsearch-suggestion--no-results{width:100%;padding:8px 0;text-align:center;font-size:1.2em}.algolia-autocomplete .algolia-docsearch-suggestion--no-results:before{display:none}.algolia-autocomplete .algolia-docsearch-suggestion code{padding:1px 5px;font-size:90%;border:none;color:#222;background-color:#ebebeb;border-radius:3px;font-family:Menlo,Monaco,Consolas,Courier New,monospace}.algolia-autocomplete .algolia-docsearch-suggestion code .algolia-docsearch-suggestion--highlight{background:none}.algolia-autocomplete .algolia-docsearch-suggestion.algolia-docsearch-suggestion__main .algolia-docsearch-suggestion--category-header,.algolia-autocomplete .algolia-docsearch-suggestion.algolia-docsearch-suggestion__secondary{display:block}@media (min-width:768px){.algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column{display:block}}@media (max-width:768px){.algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column{display:inline-block;width:auto;float:left;padding:0;color:#02060c;font-size:.9em;font-weight:700;text-align:left;opacity:.5}.algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column:before{display:none}.algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column:after{content:"|"}.algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--content{display:inline-block;width:auto;text-align:left;float:left;padding:0}.algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--content:before{display:none}}.algolia-autocomplete .suggestion-layout-simple.algolia-docsearch-suggestion{border-bottom:1px solid #eee;padding:8px;margin:0}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--content{width:100%;padding:0}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--content:before{display:none}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--category-header{margin:0;padding:0;display:block;width:100%;border:none}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--category-header-lvl0,.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--category-header-lvl1{opacity:.6;font-size:.85em}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--category-header-lvl1:before{background-image:url('data:image/svg+xml;utf8,');content:"";width:10px;height:10px;display:inline-block}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--wrapper{width:100%;float:left;margin:0;padding:0}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--duplicate-content,.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--subcategory-inline{display:none!important}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--title{margin:0;color:#458ee1;font-size:.9em;font-weight:400}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--title:before{content:"#";font-weight:700;color:#458ee1;display:inline-block}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--text{margin:4px 0 0;display:block;line-height:1.4em;padding:5.33333px 8px;background:#f8f8f8;font-size:.85em;opacity:.8}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--text .algolia-docsearch-suggestion--highlight{color:#3f4145;font-weight:700;box-shadow:none}.algolia-autocomplete .algolia-docsearch-footer{width:134px;height:20px;z-index:2000;margin-top:10.66667px;float:right;font-size:0;line-height:0}.algolia-autocomplete .algolia-docsearch-footer--logo{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg width='168' height='24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cpath d='M78.988.938h16.594a2.968 2.968 0 0 1 2.966 2.966V20.5a2.967 2.967 0 0 1-2.966 2.964H78.988a2.967 2.967 0 0 1-2.966-2.964V3.897A2.961 2.961 0 0 1 78.988.938zm41.937 17.866c-4.386.02-4.386-3.54-4.386-4.106l-.007-13.336 2.675-.424v13.254c0 .322 0 2.358 1.718 2.364v2.248zm-10.846-2.18c.821 0 1.43-.047 1.855-.129v-2.719a6.334 6.334 0 0 0-1.574-.199 5.7 5.7 0 0 0-.897.069 2.699 2.699 0 0 0-.814.24c-.24.116-.439.28-.582.491-.15.212-.219.335-.219.656 0 .628.219.991.616 1.23s.938.362 1.615.362zm-.233-9.7c.883 0 1.629.109 2.231.328.602.218 1.088.525 1.444.915.363.396.609.922.76 1.483.157.56.232 1.175.232 1.85v6.874a32.5 32.5 0 0 1-1.868.314c-.834.123-1.772.185-2.813.185-.69 0-1.327-.069-1.895-.198a4.001 4.001 0 0 1-1.471-.636 3.085 3.085 0 0 1-.951-1.134c-.226-.465-.343-1.12-.343-1.803 0-.656.13-1.073.384-1.525a3.24 3.24 0 0 1 1.047-1.106c.445-.287.95-.492 1.532-.615a8.8 8.8 0 0 1 1.82-.185 8.404 8.404 0 0 1 1.972.24v-.438c0-.307-.035-.6-.11-.874a1.88 1.88 0 0 0-.384-.73 1.784 1.784 0 0 0-.724-.493 3.164 3.164 0 0 0-1.143-.205c-.616 0-1.177.075-1.69.164a7.735 7.735 0 0 0-1.26.307l-.321-2.192c.335-.117.834-.233 1.478-.349a10.98 10.98 0 0 1 2.073-.178zm52.842 9.626c.822 0 1.43-.048 1.854-.13V13.7a6.347 6.347 0 0 0-1.574-.199c-.294 0-.595.021-.896.069a2.7 2.7 0 0 0-.814.24 1.46 1.46 0 0 0-.582.491c-.15.212-.218.335-.218.656 0 .628.218.991.615 1.23.404.245.938.362 1.615.362zm-.226-9.694c.883 0 1.629.108 2.231.327.602.219 1.088.526 1.444.915.355.39.609.923.759 1.483a6.8 6.8 0 0 1 .233 1.852v6.873c-.41.088-1.034.19-1.868.314-.834.123-1.772.184-2.813.184-.69 0-1.327-.068-1.895-.198a4.001 4.001 0 0 1-1.471-.635 3.085 3.085 0 0 1-.951-1.134c-.226-.465-.343-1.12-.343-1.804 0-.656.13-1.073.384-1.524.26-.45.608-.82 1.047-1.107.445-.286.95-.491 1.532-.614a8.803 8.803 0 0 1 2.751-.13c.329.034.671.096 1.04.185v-.437a3.3 3.3 0 0 0-.109-.875 1.873 1.873 0 0 0-.384-.731 1.784 1.784 0 0 0-.724-.492 3.165 3.165 0 0 0-1.143-.205c-.616 0-1.177.075-1.69.164a7.75 7.75 0 0 0-1.26.307l-.321-2.193c.335-.116.834-.232 1.478-.348a11.633 11.633 0 0 1 2.073-.177zm-8.034-1.271a1.626 1.626 0 0 1-1.628-1.62c0-.895.725-1.62 1.628-1.62.904 0 1.63.725 1.63 1.62 0 .895-.733 1.62-1.63 1.62zm1.348 13.22h-2.689V7.27l2.69-.423v11.956zm-4.714 0c-4.386.02-4.386-3.54-4.386-4.107l-.008-13.336 2.676-.424v13.254c0 .322 0 2.358 1.718 2.364v2.248zm-8.698-5.903c0-1.156-.253-2.119-.746-2.788-.493-.677-1.183-1.01-2.067-1.01-.882 0-1.574.333-2.065 1.01-.493.676-.733 1.632-.733 2.788 0 1.168.246 1.953.74 2.63.492.683 1.183 1.018 2.066 1.018.882 0 1.574-.342 2.067-1.019.492-.683.738-1.46.738-2.63zm2.737-.007c0 .902-.13 1.584-.397 2.33a5.52 5.52 0 0 1-1.128 1.906 4.986 4.986 0 0 1-1.752 1.223c-.685.286-1.739.45-2.265.45-.528-.006-1.574-.157-2.252-.45a5.096 5.096 0 0 1-1.744-1.223c-.487-.527-.863-1.162-1.137-1.906a6.345 6.345 0 0 1-.41-2.33c0-.902.123-1.77.397-2.508a5.554 5.554 0 0 1 1.15-1.892 5.133 5.133 0 0 1 1.75-1.216c.679-.287 1.425-.423 2.232-.423.808 0 1.553.142 2.237.423a4.88 4.88 0 0 1 1.753 1.216 5.644 5.644 0 0 1 1.135 1.892c.287.738.431 1.606.431 2.508zm-20.138 0c0 1.12.246 2.363.738 2.882.493.52 1.13.78 1.91.78.424 0 .828-.062 1.204-.178.377-.116.677-.253.917-.417V9.33a10.476 10.476 0 0 0-1.766-.226c-.971-.028-1.71.37-2.23 1.004-.513.636-.773 1.75-.773 2.788zm7.438 5.274c0 1.824-.466 3.156-1.404 4.004-.936.846-2.367 1.27-4.296 1.27-.705 0-2.17-.137-3.34-.396l.431-2.118c.98.205 2.272.26 2.95.26 1.074 0 1.84-.219 2.299-.656.459-.437.684-1.086.684-1.948v-.437a8.07 8.07 0 0 1-1.047.397c-.43.13-.93.198-1.492.198-.739 0-1.41-.116-2.018-.349a4.206 4.206 0 0 1-1.567-1.025c-.431-.45-.774-1.017-1.013-1.694-.24-.677-.363-1.885-.363-2.773 0-.834.13-1.88.384-2.577.26-.696.629-1.298 1.129-1.796.493-.498 1.095-.881 1.8-1.162a6.605 6.605 0 0 1 2.428-.457c.87 0 1.67.109 2.45.24.78.129 1.444.265 1.985.415V18.17z' fill='%235468FF'/%3E%3Cpath d='M6.972 6.677v1.627c-.712-.446-1.52-.67-2.425-.67-.585 0-1.045.13-1.38.391a1.24 1.24 0 0 0-.502 1.03c0 .425.164.765.494 1.02.33.256.835.532 1.516.83.447.192.795.356 1.045.495.25.138.537.332.862.582.324.25.563.548.718.894.154.345.23.741.23 1.188 0 .947-.334 1.691-1.004 2.234-.67.542-1.537.814-2.601.814-1.18 0-2.16-.229-2.936-.686v-1.708c.84.628 1.814.942 2.92.942.585 0 1.048-.136 1.388-.407.34-.271.51-.646.51-1.125 0-.287-.1-.55-.302-.79-.203-.24-.42-.42-.655-.542-.234-.123-.585-.29-1.053-.503a61.27 61.27 0 0 1-.582-.271 13.67 13.67 0 0 1-.55-.287 4.275 4.275 0 0 1-.567-.351 6.92 6.92 0 0 1-.455-.4c-.18-.17-.31-.34-.39-.51-.08-.17-.155-.37-.224-.598a2.553 2.553 0 0 1-.104-.742c0-.915.333-1.638.998-2.17.664-.532 1.523-.798 2.576-.798.968 0 1.793.17 2.473.51zm7.468 5.696v-.287c-.022-.607-.187-1.088-.495-1.444-.309-.357-.75-.535-1.324-.535-.532 0-.99.194-1.373.583-.382.388-.622.949-.717 1.683h3.909zm1.005 2.792v1.404c-.596.34-1.383.51-2.362.51-1.255 0-2.255-.377-3-1.132-.744-.755-1.116-1.744-1.116-2.968 0-1.297.34-2.316 1.021-3.055.68-.74 1.548-1.11 2.6-1.11 1.033 0 1.852.323 2.458.966.606.644.91 1.572.91 2.784 0 .33-.033.676-.096 1.038h-5.314c.107.702.405 1.239.894 1.611.49.372 1.106.558 1.85.558.862 0 1.58-.202 2.155-.606zm6.605-1.77h-1.212c-.596 0-1.045.116-1.349.35-.303.234-.454.532-.454.894 0 .372.117.664.35.877.235.213.575.32 1.022.32.51 0 .912-.142 1.204-.424.293-.281.44-.651.44-1.108v-.91zm-4.068-2.554V9.325c.627-.361 1.457-.542 2.489-.542 2.116 0 3.175 1.026 3.175 3.08V17h-1.548v-.957c-.415.68-1.143 1.02-2.186 1.02-.766 0-1.38-.22-1.843-.661-.462-.442-.694-1.003-.694-1.684 0-.776.293-1.38.878-1.81.585-.431 1.404-.647 2.457-.647h1.34V11.8c0-.554-.133-.971-.399-1.253-.266-.282-.707-.423-1.324-.423a4.07 4.07 0 0 0-2.345.718zm9.333-1.93v1.42c.394-1 1.101-1.5 2.123-1.5.148 0 .313.016.494.048v1.531a1.885 1.885 0 0 0-.75-.143c-.542 0-.989.24-1.34.718-.351.479-.527 1.048-.527 1.707V17h-1.563V8.91h1.563zm5.01 4.084c.022.82.272 1.492.75 2.019.479.526 1.15.79 2.01.79.639 0 1.235-.176 1.788-.527v1.404c-.521.319-1.186.479-1.995.479-1.265 0-2.276-.4-3.031-1.197-.755-.798-1.133-1.792-1.133-2.984 0-1.16.38-2.151 1.14-2.975.761-.825 1.79-1.237 3.088-1.237.702 0 1.346.149 1.93.447v1.436a3.242 3.242 0 0 0-1.77-.495c-.84 0-1.513.266-2.019.798-.505.532-.758 1.213-.758 2.042zM40.24 5.72v4.579c.458-1 1.293-1.5 2.505-1.5.787 0 1.42.245 1.899.734.479.49.718 1.17.718 2.042V17h-1.564v-5.106c0-.553-.14-.98-.422-1.284-.282-.303-.652-.455-1.11-.455-.531 0-1.002.202-1.411.606-.41.405-.615 1.022-.615 1.851V17h-1.563V5.72h1.563zm14.966 10.02c.596 0 1.096-.253 1.5-.758.404-.506.606-1.157.606-1.955 0-.915-.202-1.62-.606-2.114-.404-.495-.92-.742-1.548-.742-.553 0-1.05.224-1.491.67-.442.447-.662 1.133-.662 2.058 0 .958.212 1.67.638 2.138.425.469.946.703 1.563.703zM53.004 5.72v4.42c.574-.894 1.388-1.341 2.44-1.341 1.022 0 1.857.383 2.506 1.149.649.766.973 1.781.973 3.047 0 1.138-.309 2.109-.925 2.912-.617.803-1.463 1.205-2.537 1.205-1.075 0-1.894-.447-2.457-1.34V17h-1.58V5.72h1.58zm9.908 11.104l-3.223-7.913h1.739l1.005 2.632 1.26 3.415c.096-.32.48-1.458 1.15-3.415l.909-2.632h1.66l-2.92 7.866c-.777 2.074-1.963 3.11-3.559 3.11a2.92 2.92 0 0 1-.734-.079v-1.34c.17.042.351.064.543.064 1.032 0 1.755-.57 2.17-1.708z' fill='%235D6494'/%3E%3Cpath d='M89.632 5.967v-.772a.978.978 0 0 0-.978-.977h-2.28a.978.978 0 0 0-.978.977v.793c0 .088.082.15.171.13a7.127 7.127 0 0 1 1.984-.28c.65 0 1.295.088 1.917.259.082.02.164-.04.164-.13m-6.248 1.01l-.39-.389a.977.977 0 0 0-1.382 0l-.465.465a.973.973 0 0 0 0 1.38l.383.383c.062.061.15.047.205-.014.226-.307.472-.601.746-.874.281-.28.568-.526.883-.751.068-.042.075-.137.02-.2m4.16 2.453v3.341c0 .096.104.165.192.117l2.97-1.537c.068-.034.089-.117.055-.184a3.695 3.695 0 0 0-3.08-1.866c-.068 0-.136.054-.136.13m0 8.048a4.489 4.489 0 0 1-4.49-4.482 4.488 4.488 0 0 1 4.49-4.482 4.488 4.488 0 0 1 4.489 4.482 4.484 4.484 0 0 1-4.49 4.482m0-10.85a6.363 6.363 0 1 0 0 12.729 6.37 6.37 0 0 0 6.372-6.368 6.358 6.358 0 0 0-6.371-6.36' fill='%23FFF'/%3E%3C/g%3E%3C/svg%3E");background-repeat:no-repeat;background-position:50%;background-size:100%;overflow:hidden;text-indent:-9000px;padding:0!important;width:100%;height:100%;display:block}.algolia-search-wrapper>span{vertical-align:middle}.algolia-search-wrapper .algolia-autocomplete{line-height:normal}.algolia-search-wrapper .algolia-autocomplete .ds-dropdown-menu{background-color:#fff;border:1px solid #999;border-radius:4px;font-size:16px;margin:6px 0 0;padding:4px;text-align:left}.algolia-search-wrapper .algolia-autocomplete .ds-dropdown-menu:before{border-color:#999}.algolia-search-wrapper .algolia-autocomplete .ds-dropdown-menu [class*=ds-dataset-]{border:none;padding:0}.algolia-search-wrapper .algolia-autocomplete .ds-dropdown-menu .ds-suggestions{margin-top:0}.algolia-search-wrapper .algolia-autocomplete .ds-dropdown-menu .ds-suggestion{border-bottom:1px solid #eaecef}.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-suggestion--highlight{color:#2c815b}.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-suggestion{border-color:#eaecef;padding:0}.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--category-header{padding:5px 10px;margin-top:0;background:#3eaf7c;color:#fff;font-weight:600}.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--category-header .algolia-docsearch-suggestion--highlight{background:hsla(0,0%,100%,.6)}.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--wrapper{padding:0}.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--title{font-weight:600;margin-bottom:0;color:#2c3e50}.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column{vertical-align:top;padding:5px 7px 5px 5px;border-color:#eaecef;background:#f1f3f5}.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column:after{display:none}.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column-text{color:#555}.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-footer{border-color:#eaecef}.algolia-search-wrapper .algolia-autocomplete .ds-cursor .algolia-docsearch-suggestion--content{background-color:#e7edf3!important;color:#2c3e50}@media (min-width:719px){.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column{float:none;width:150px;min-width:150px;display:table-cell}.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--content{float:none;display:table-cell;width:100%;vertical-align:top}.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-suggestion .ds-dropdown-menu{min-width:515px!important}}@media (max-width:719px){.algolia-search-wrapper .ds-dropdown-menu{min-width:calc(100vw - 4rem)!important;max-width:calc(100vw - 4rem)!important}.algolia-search-wrapper .algolia-docsearch-suggestion--wrapper{padding:5px 7px 5px 5px!important}.algolia-search-wrapper .algolia-docsearch-suggestion--subcategory-column{padding:0!important;background:#fff!important}.algolia-search-wrapper .algolia-docsearch-suggestion--subcategory-column-text:after{content:" > ";font-size:10px;line-height:14.4px;display:inline-block;width:5px;margin:-3px 3px 0;vertical-align:middle}}.search-box{display:inline-block;position:relative;margin-right:1rem}.search-box input{cursor:text;width:10rem;color:#4e6e8e;display:inline-block;border:1px solid #cfd4db;border-radius:2rem;font-size:.9rem;line-height:2rem;padding:0 .5rem 0 2rem;outline:none;transition:all .2s ease;background:#fff url(/assets/img/search.83621669.svg) .6rem .5rem no-repeat;background-size:1rem}.search-box input:focus{cursor:auto;border-color:#3eaf7c}.search-box .suggestions{background:#fff;width:20rem;position:absolute;top:1.5rem;border:1px solid #cfd4db;border-radius:6px;padding:.4rem;list-style-type:none}.search-box .suggestions.align-right{right:0}.search-box .suggestion{line-height:1.4;padding:.4rem .6rem;border-radius:4px;cursor:pointer}.search-box .suggestion a{white-space:normal;color:#5d82a6}.search-box .suggestion a .page-title{font-weight:600}.search-box .suggestion a .header{font-size:.9em;margin-left:.25em}.search-box .suggestion.focused{background-color:#f3f4f5}.search-box .suggestion.focused a{color:#3eaf7c}@media (max-width:959px){.search-box input{cursor:pointer;width:0;border-color:transparent;position:relative}.search-box input:focus{cursor:text;left:0;width:10rem}}@media (max-width:959px) and (min-width:719px){.search-box .suggestions{left:0}}@media (max-width:719px){.search-box{margin-right:0}.search-box input{left:1rem}.search-box .suggestions{right:0}}@media (max-width:419px){.search-box .suggestions{width:calc(100vw - 4rem)}.search-box input:focus{width:8rem}}.dropdown-enter,.dropdown-leave-to{height:0!important}.dropdown-wrapper{cursor:pointer}.dropdown-wrapper .dropdown-title{display:block}.dropdown-wrapper .dropdown-title:hover{border-color:transparent}.dropdown-wrapper .dropdown-title .arrow{vertical-align:middle;margin-top:-1px;margin-left:.4rem}.dropdown-wrapper .nav-dropdown .dropdown-item{color:inherit;line-height:1.7rem}.dropdown-wrapper .nav-dropdown .dropdown-item h4{margin:.45rem 0 0;border-top:1px solid #eee;padding:.45rem 1.5rem 0 1.25rem}.dropdown-wrapper .nav-dropdown .dropdown-item .dropdown-subitem-wrapper{padding:0;list-style:none}.dropdown-wrapper .nav-dropdown .dropdown-item .dropdown-subitem-wrapper .dropdown-subitem{font-size:.9em}.dropdown-wrapper .nav-dropdown .dropdown-item a{display:block;line-height:1.7rem;position:relative;border-bottom:none;font-weight:400;margin-bottom:0;padding:0 1.5rem 0 1.25rem}.dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active,.dropdown-wrapper .nav-dropdown .dropdown-item a:hover{color:#3eaf7c}.dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active:after{content:"";width:0;height:0;border-left:5px solid #3eaf7c;border-top:3px solid transparent;border-bottom:3px solid transparent;position:absolute;top:calc(50% - 2px);left:9px}.dropdown-wrapper .nav-dropdown .dropdown-item:first-child h4{margin-top:0;padding-top:0;border-top:0}@media (max-width:719px){.dropdown-wrapper.open .dropdown-title{margin-bottom:.5rem}.dropdown-wrapper .nav-dropdown{transition:height .1s ease-out;overflow:hidden}.dropdown-wrapper .nav-dropdown .dropdown-item h4{border-top:0;margin-top:0;padding-top:0}.dropdown-wrapper .nav-dropdown .dropdown-item>a,.dropdown-wrapper .nav-dropdown .dropdown-item h4{font-size:15px;line-height:2rem}.dropdown-wrapper .nav-dropdown .dropdown-item .dropdown-subitem{font-size:14px;padding-left:1rem}}@media (min-width:719px){.dropdown-wrapper{height:1.8rem}.dropdown-wrapper:hover .nav-dropdown{display:block!important}.dropdown-wrapper .dropdown-title .arrow{border-left:4px solid transparent;border-right:4px solid transparent;border-top:6px solid #ccc;border-bottom:0}.dropdown-wrapper .nav-dropdown{display:none;height:auto!important;box-sizing:border-box;max-height:calc(100vh - 2.7rem);overflow-y:auto;position:absolute;top:100%;right:0;background-color:#fff;padding:.6rem 0;border:1px solid #ddd;border-bottom-color:#ccc;text-align:left;border-radius:.25rem;white-space:nowrap;margin:0}}.nav-links{display:inline-block}.nav-links a{line-height:1.4rem;color:inherit}.nav-links a.router-link-active,.nav-links a:hover{color:#3eaf7c}.nav-links .nav-item{position:relative;display:inline-block;margin-left:1.5rem;line-height:2rem}.nav-links .nav-item:first-child{margin-left:0}.nav-links .repo-link{margin-left:1.5rem}@media (max-width:719px){.nav-links .nav-item,.nav-links .repo-link{margin-left:0}}@media (min-width:719px){.nav-links a.router-link-active,.nav-links a:hover{color:#2c3e50}.nav-item>a:not(.external).router-link-active,.nav-item>a:not(.external):hover{margin-bottom:-2px;border-bottom:2px solid #46bd87}}.navbar{padding:.7rem 1.5rem;line-height:2.2rem;position:relative}.navbar a,.navbar img,.navbar span{display:inline-block}.navbar .logo{height:2.2rem;min-width:2.2rem;margin-right:.8rem;vertical-align:top}.navbar .site-name{font-size:1.3rem;font-weight:600;color:#2c3e50;position:relative}.navbar .links{padding-left:1.5rem;box-sizing:border-box;background-color:#fff;white-space:nowrap;font-size:.9rem;position:absolute;right:1.5rem;top:.7rem;display:flex}.navbar .links .search-box{flex:0 0 auto;vertical-align:top}.navbar .links .nav-links{flex:1}@media (max-width:719px){.navbar{padding-left:4rem}.navbar .can-hide{display:none}.navbar .links{padding-left:1.5rem}}.page-edit,.page-nav{max-width:740px;margin:0 auto;padding:2rem 2.5rem}@media (max-width:959px){.page-edit,.page-nav{padding:2rem}}@media (max-width:419px){.page-edit,.page-nav{padding:1.5rem}}.page{padding-bottom:2rem}.page-edit{padding-top:1rem;padding-bottom:1rem;overflow:auto}.page-edit .edit-link{display:inline-block}.page-edit .edit-link a{color:#4e6e8e;margin-right:.25rem}.page-edit .last-updated{float:right;font-size:.9em}.page-edit .last-updated .prefix{font-weight:500;color:#4e6e8e}.page-edit .last-updated .time{font-weight:400;color:#aaa}.page-nav{padding-top:1rem;padding-bottom:0}.page-nav .inner{min-height:2rem;margin-top:0;border-top:1px solid #eaecef;padding-top:1rem;overflow:auto}.page-nav .next{float:right}@media (max-width:719px){.page-edit .edit-link{margin-bottom:.5rem}.page-edit .last-updated{font-size:.8em;float:none;text-align:left}}.sidebar .sidebar-sub-headers{padding-left:1rem;font-size:.95em}a.sidebar-link{font-weight:400;display:inline-block;color:#2c3e50;border-left:.25rem solid transparent;padding:.35rem 1rem .35rem 1.25rem;line-height:1.4;width:100%;box-sizing:border-box}a.sidebar-link:hover{color:#3eaf7c}a.sidebar-link.active{font-weight:600;color:#3eaf7c;border-left-color:#3eaf7c}.sidebar-group a.sidebar-link{padding-left:2rem}.sidebar-sub-headers a.sidebar-link{padding-top:.25rem;padding-bottom:.25rem;border-left:none}.sidebar-sub-headers a.sidebar-link.active{font-weight:500}.sidebar-button{display:none;width:1.25rem;height:1.25rem;position:absolute;padding:.6rem;top:.6rem;left:1rem;cursor:pointer}.sidebar-button .icon{display:block;width:1.25rem;height:1.25rem}@media (max-width:719px){.sidebar-button{display:block}}.sidebar ul{padding:0;margin:0;list-style-type:none}.sidebar a{display:inline-block}.sidebar .nav-links{display:none;border-bottom:1px solid #eaecef;padding:.5rem 0 .75rem 0}.sidebar .nav-links a{font-weight:600}.sidebar .nav-links .nav-item,.sidebar .nav-links .repo-link{display:block;line-height:1.25rem;font-size:1.1em;padding:.5rem 0 .5rem 1.5rem}.sidebar .sidebar-links{padding:1.5rem 0}@media (max-width:719px){.sidebar .nav-links{display:block}.sidebar .nav-links .dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active:after{top:calc(1rem - 2px)}.sidebar .sidebar-links{padding:1rem 0}}.sw-update-popup{position:fixed;right:1em;bottom:1em;padding:1em;border:1px solid #3eaf7c;border-radius:3px;background:#fff;box-shadow:0 4px 16px rgba(0,0,0,.5);text-align:center}.sw-update-popup button{margin-top:.5em;padding:.25em 2em}.sw-update-popup-enter-active,.sw-update-popup-leave-active{transition:opacity .3s,transform .3s}.sw-update-popup-enter,.sw-update-popup-leave-to{opacity:0;transform:translateY(50%) scale(.5)}code[class*=language-],pre[class*=language-]{color:#ccc;background:none;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-ms-hyphens:none;hyphens:none}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#2d2d2d}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.block-comment,.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#999}.token.punctuation{color:#ccc}.token.attr-name,.token.deleted,.token.namespace,.token.tag{color:#e2777a}.token.function-name{color:#6196cc}.token.boolean,.token.function,.token.number{color:#f08d49}.token.class-name,.token.constant,.token.property,.token.symbol{color:#f8c555}.token.atrule,.token.builtin,.token.important,.token.keyword,.token.selector{color:#cc99cd}.token.attr-value,.token.char,.token.regex,.token.string,.token.variable{color:#7ec699}.token.entity,.token.operator,.token.url{color:#67cdcc}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.token.inserted{color:green}#nprogress{pointer-events:none}#nprogress .bar{background:#3eaf7c;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #3eaf7c,0 0 5px #3eaf7c;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#3eaf7c;border-left-color:#3eaf7c;border-radius:50%;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.content code{color:#476582;padding:.25rem .5rem;margin:0;font-size:.85em;background-color:rgba(27,31,35,.05);border-radius:3px}.content pre,.content pre[class*=language-]{line-height:1.4;padding:1.25rem 1.5rem;margin:.85rem 0;background-color:#282c34;border-radius:6px;overflow:auto}.content pre[class*=language-] code,.content pre code{color:#fff;padding:0;background-color:transparent;border-radius:0}div[class*=language-]{position:relative;background-color:#282c34;border-radius:6px}div[class*=language-] .highlight-lines{-webkit-user-select:none;-ms-user-select:none;user-select:none;padding-top:1.3rem;position:absolute;top:0;left:0;width:100%;line-height:1.4}div[class*=language-] .highlight-lines .highlighted{background-color:rgba(0,0,0,.66)}div[class*=language-] pre,div[class*=language-] pre[class*=language-]{background:transparent;position:relative;z-index:1}div[class*=language-]:before{position:absolute;z-index:3;top:.8em;right:1em;font-size:.75rem;color:hsla(0,0%,100%,.4)}div[class*=language-]:not(.line-numbers-mode) .line-numbers-wrapper{display:none}div[class*=language-].line-numbers-mode .highlight-lines .highlighted{position:relative}div[class*=language-].line-numbers-mode .highlight-lines .highlighted:before{content:" ";position:absolute;z-index:3;left:0;top:0;display:block;width:3.5rem;height:100%;background-color:rgba(0,0,0,.66)}div[class*=language-].line-numbers-mode pre{padding-left:4.5rem;vertical-align:middle}div[class*=language-].line-numbers-mode .line-numbers-wrapper{position:absolute;top:0;width:3.5rem;text-align:center;color:hsla(0,0%,100%,.3);padding:1.25rem 0;line-height:1.4}div[class*=language-].line-numbers-mode .line-numbers-wrapper br{-webkit-user-select:none;-ms-user-select:none;user-select:none}div[class*=language-].line-numbers-mode .line-numbers-wrapper .line-number{position:relative;z-index:4;-webkit-user-select:none;-ms-user-select:none;user-select:none;font-size:.85em}div[class*=language-].line-numbers-mode:after{content:"";position:absolute;z-index:2;top:0;left:0;width:3.5rem;height:100%;border-radius:6px 0 0 6px;border-right:1px solid rgba(0,0,0,.66);background-color:#282c34}div[class~=language-js]:before{content:"js"}div[class~=language-ts]:before{content:"ts"}div[class~=language-html]:before{content:"html"}div[class~=language-md]:before{content:"md"}div[class~=language-vue]:before{content:"vue"}div[class~=language-css]:before{content:"css"}div[class~=language-sass]:before{content:"sass"}div[class~=language-scss]:before{content:"scss"}div[class~=language-less]:before{content:"less"}div[class~=language-stylus]:before{content:"stylus"}div[class~=language-go]:before{content:"go"}div[class~=language-java]:before{content:"java"}div[class~=language-c]:before{content:"c"}div[class~=language-sh]:before{content:"sh"}div[class~=language-yaml]:before{content:"yaml"}div[class~=language-py]:before{content:"py"}div[class~=language-javascript]:before{content:"js"}div[class~=language-typescript]:before{content:"ts"}div[class~=language-markup]:before{content:"html"}div[class~=language-markdown]:before{content:"md"}div[class~=language-json]:before{content:"json"}div[class~=language-ruby]:before{content:"rb"}div[class~=language-python]:before{content:"py"}div[class~=language-bash]:before{content:"sh"}.custom-block .custom-block-title{font-weight:600;margin-bottom:-.4rem}.custom-block.danger,.custom-block.tip,.custom-block.warning{padding:.1rem 1.5rem;border-left-width:.5rem;border-left-style:solid;margin:1rem 0}.custom-block.tip{background-color:#f3f5f7;border-color:#42b983}.custom-block.warning{background-color:rgba(255,229,100,.3);border-color:#e7c000;color:#6b5900}.custom-block.warning .custom-block-title{color:#b29400}.custom-block.warning a{color:#2c3e50}.custom-block.danger{background-color:#ffe6e6;border-color:#c00;color:#4d0000}.custom-block.danger .custom-block-title{color:#900}.custom-block.danger a{color:#2c3e50}.arrow{display:inline-block;width:0;height:0}.arrow.up{border-bottom:6px solid #ccc}.arrow.down,.arrow.up{border-left:4px solid transparent;border-right:4px solid transparent}.arrow.down{border-top:6px solid #ccc}.arrow.right{border-left:6px solid #ccc}.arrow.left,.arrow.right{border-top:4px solid transparent;border-bottom:4px solid transparent}.arrow.left{border-right:6px solid #ccc}.content:not(.custom){max-width:740px;margin:0 auto;padding:2rem 2.5rem}@media (max-width:959px){.content:not(.custom){padding:2rem}}@media (max-width:419px){.content:not(.custom){padding:1.5rem}}.table-of-contents .badge{vertical-align:middle}body,html{padding:0;margin:0}body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-size:16px;color:#2c3e50}.page{padding-left:20rem}.navbar{z-index:20;right:0;height:3.6rem;background-color:#fff;box-sizing:border-box;border-bottom:1px solid #eaecef}.navbar,.sidebar-mask{position:fixed;top:0;left:0}.sidebar-mask{z-index:9;width:100vw;height:100vh;display:none}.sidebar{font-size:15px;background-color:#fff;width:20rem;position:fixed;z-index:10;margin:0;top:3.6rem;left:0;bottom:0;box-sizing:border-box;border-right:1px solid #eaecef;overflow-y:auto}.content:not(.custom)>:first-child{margin-top:3.6rem}.content:not(.custom) a:hover{text-decoration:underline}.content:not(.custom) p.demo{padding:1rem 1.5rem;border:1px solid #ddd;border-radius:4px}.content:not(.custom) img{max-width:100%}.content.custom{padding:0;margin:0}.content.custom img{max-width:100%}a{font-weight:500;text-decoration:none}a,p a code{color:#3eaf7c}p a code{font-weight:400}kbd{background:#eee;border:.15rem solid #ddd;border-bottom:.25rem solid #ddd;border-radius:.15rem;padding:0 .15em}blockquote{font-size:1.2rem;color:#999;border-left:.25rem solid #dfe2e5;margin-left:0;padding-left:1rem}ol,ul{padding-left:1.2em}strong{font-weight:600}h1,h2,h3,h4,h5,h6{font-weight:600;line-height:1.25}.content:not(.custom)>h1,.content:not(.custom)>h2,.content:not(.custom)>h3,.content:not(.custom)>h4,.content:not(.custom)>h5,.content:not(.custom)>h6{margin-top:-3.1rem;padding-top:4.6rem;margin-bottom:0}.content:not(.custom)>h1:first-child,.content:not(.custom)>h2:first-child,.content:not(.custom)>h3:first-child,.content:not(.custom)>h4:first-child,.content:not(.custom)>h5:first-child,.content:not(.custom)>h6:first-child{margin-top:-1.5rem;margin-bottom:1rem}.content:not(.custom)>h1:first-child+.custom-block,.content:not(.custom)>h1:first-child+p,.content:not(.custom)>h1:first-child+pre,.content:not(.custom)>h2:first-child+.custom-block,.content:not(.custom)>h2:first-child+p,.content:not(.custom)>h2:first-child+pre,.content:not(.custom)>h3:first-child+.custom-block,.content:not(.custom)>h3:first-child+p,.content:not(.custom)>h3:first-child+pre,.content:not(.custom)>h4:first-child+.custom-block,.content:not(.custom)>h4:first-child+p,.content:not(.custom)>h4:first-child+pre,.content:not(.custom)>h5:first-child+.custom-block,.content:not(.custom)>h5:first-child+p,.content:not(.custom)>h5:first-child+pre,.content:not(.custom)>h6:first-child+.custom-block,.content:not(.custom)>h6:first-child+p,.content:not(.custom)>h6:first-child+pre{margin-top:2rem}h1:hover .header-anchor,h2:hover .header-anchor,h3:hover .header-anchor,h4:hover .header-anchor,h5:hover .header-anchor,h6:hover .header-anchor{opacity:1}h1{font-size:2.2rem}h2{font-size:1.65rem;padding-bottom:.3rem;border-bottom:1px solid #eaecef}h3{font-size:1.35rem}a.header-anchor{font-size:.85em;float:left;margin-left:-.87em;padding-right:.23em;margin-top:.125em;opacity:0}a.header-anchor:hover{text-decoration:none}.line-number,code,kbd{font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}ol,p,ul{line-height:1.7}hr{border:0;border-top:1px solid #eaecef}table{border-collapse:collapse;margin:1rem 0;display:block;overflow-x:auto}tr{border-top:1px solid #dfe2e5}tr:nth-child(2n){background-color:#f6f8fa}td,th{border:1px solid #dfe2e5;padding:.6em 1em}.custom-layout{padding-top:3.6rem}.theme-container.sidebar-open .sidebar-mask{display:block}.theme-container.no-navbar .content:not(.custom)>h1,.theme-container.no-navbar h2,.theme-container.no-navbar h3,.theme-container.no-navbar h4,.theme-container.no-navbar h5,.theme-container.no-navbar h6{margin-top:1.5rem;padding-top:0}.theme-container.no-navbar .sidebar{top:0}.theme-container.no-navbar .custom-layout{padding-top:0}@media (min-width:720px){.theme-container.no-sidebar .sidebar{display:none}.theme-container.no-sidebar .page{padding-left:0}}@media (max-width:959px){.sidebar{font-size:15px;width:16.4rem}.page{padding-left:16.4rem}}@media (max-width:719px){.sidebar{top:0;padding-top:3.6rem;transform:translateX(-100%);transition:transform .2s ease}.page{padding-left:0}.theme-container.sidebar-open .sidebar{transform:translateX(0)}.theme-container.no-navbar .sidebar{padding-top:0}}@media (max-width:419px){h1{font-size:1.9rem}.content div[class*=language-]{margin:.85rem -1.5rem;border-radius:0}}.bsa-cpc-wrapper{font-size:.95rem;max-width:740px;margin:0 auto;padding:1rem 2rem 0;margin-bottom:-1rem}@media (max-width:419px){.bsa-cpc-wrapper{padding:0 1.5rem}}.bsa-cpc{font-size:.9em;background-color:#f8f8f8;border-radius:6px}.bsa-cpc a._default_{text-align:left;display:block;padding:10px 15px 12px;margin-bottom:20px;color:#666;font-weight:400;line-height:18px}.bsa-cpc a._default_ .default-image img{height:20px;border-radius:3px;vertical-align:middle;position:relative;top:-1px}.bsa-cpc a._default_ .default-title{font-weight:600}.bsa-cpc a._default_ .default-description:after{font-size:.85em;content:"Sponsored";color:#1c90f3;border:1px solid #1c90f3;border-radius:3px;padding:0 4px 1px;margin-left:6px}.bsa-cpc .default-ad{display:none}.bsa-cpc a._default_ .default-description,.bsa-cpc a._default_ .default-image,.bsa-cpc a._default_ .default-title{display:inline;vertical-align:middle;margin-right:6px}.icon.outbound{color:#aaa;display:inline-block}.badge[data-v-099ab69c]{display:inline-block;font-size:14px;height:18px;line-height:18px;border-radius:3px;padding:0 6px;color:#fff;margin-right:5px;background-color:#42b983}.badge.middle[data-v-099ab69c]{vertical-align:middle}.badge.top[data-v-099ab69c]{vertical-align:top}.badge.green[data-v-099ab69c],.badge.tip[data-v-099ab69c]{background-color:#42b983}.badge.error[data-v-099ab69c]{background-color:#da5961}.badge.warn[data-v-099ab69c],.badge.warning[data-v-099ab69c],.badge.yellow[data-v-099ab69c]{background-color:#e7c000}.sidebar-group:not(.first){margin-top:1em}.sidebar-group .sidebar-group{padding-left:.5em}.sidebar-group:not(.collapsable) .sidebar-heading{cursor:auto;color:inherit}.sidebar-heading{color:#999;transition:color .15s ease;cursor:pointer;font-size:1.1em;font-weight:700;padding:0 1.5rem;margin-top:0;margin-bottom:.5rem}.sidebar-heading.open,.sidebar-heading:hover{color:inherit}.sidebar-heading .arrow{position:relative;top:-.12em;left:.5em}.sidebar-heading:.open .arrow{top:-.18em}.sidebar-group-items{transition:height .1s ease-out;overflow:hidden} \ No newline at end of file diff --git a/vue-loader/assets/img/search.83621669.svg b/vue-loader/assets/img/search.83621669.svg new file mode 100644 index 000000000..03d83913e --- /dev/null +++ b/vue-loader/assets/img/search.83621669.svg @@ -0,0 +1 @@ + diff --git a/vue-loader/assets/js/10.a114b627.js b/vue-loader/assets/js/10.a114b627.js new file mode 100644 index 000000000..12ca6b719 --- /dev/null +++ b/vue-loader/assets/js/10.a114b627.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[10],{204:function(t,a,s){"use strict";s.r(a);var e=s(0),n=Object(e.a)({},(function(){var t=this,a=t.$createElement,s=t._self._c||a;return s("div",{staticClass:"content"},[t._m(0),t._v(" "),t._m(1),t._v(" "),t._m(2),t._v(" "),s("p",[t._v("Expressions in the template are evaluated in the "),s("a",{attrs:{href:"https://vuejs.org/v2/guide/render-function.html#Functional-Components",target:"_blank",rel:"noopener noreferrer"}},[t._v("functional render context"),s("OutboundLink")],1),t._v(". This means props need to be accessed as "),s("code",[t._v("props.xxx")]),t._v(" in the template:")]),t._v(" "),t._m(3),t._m(4),t._v(" "),t._m(5)])}),[function(){var t=this.$createElement,a=this._self._c||t;return a("h1",{attrs:{id:"functional-components"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#functional-components"}},[this._v("#")]),this._v(" Functional Components")])},function(){var t=this.$createElement,a=this._self._c||t;return a("p",[this._v("Functional components defined as a Single-File Component in a "),a("code",[this._v("*.vue")]),this._v(" file also receives proper template compilation, Scoped CSS and hot-reloading support.")])},function(){var t=this.$createElement,a=this._self._c||t;return a("p",[this._v("To denote a template that should be compiled as a functional component, add the "),a("code",[this._v("functional")]),this._v(" attribute to the template block. This also allows omitting the "),a("code",[this._v("functional")]),this._v(" option in the "),a("code",[this._v(" + + diff --git a/vue-loader/guide/css-modules.html b/vue-loader/guide/css-modules.html new file mode 100644 index 000000000..da0336fc8 --- /dev/null +++ b/vue-loader/guide/css-modules.html @@ -0,0 +1,122 @@ + + + + + + CSS Modules | Vue Loader 中文文档 + + + + + + + +

# CSS Modules

CSS Modules is a popular system for modularizing and composing CSS. vue-loader provides first-class integration with CSS Modules as an alternative for simulated scoped CSS.

# Usage

First, CSS Modules must be enabled by passing modules: true to css-loader:

// webpack.config.js
+{
+  module: {
+    rules: [
+      // ... other rules omitted
+      {
+        test: /\.css$/,
+        use: [
+          'vue-style-loader',
+          {
+            loader: 'css-loader',
+            options: {
+              // enable CSS Modules
+              modules: true,
+              // customize generated class names
+              localIdentName: '[local]_[hash:base64:8]'
+            }
+          }
+        ]
+      }
+    ]
+  }
+}
+

Then, add the module attribute to your <style>:

<style module>
+.red {
+  color: red;
+}
+.bold {
+  font-weight: bold;
+}
+</style>
+

The module attribute instructs Vue Loader to inject the CSS modules locals object into the component as a computed property with the name $style. You can then use it in your templates with a dynamic class binding:

<template>
+  <p :class="$style.red">
+    This should be red
+  </p>
+</template>
+

Since it's a computed property, it also works with the object/array syntax of :class:

<template>
+  <div>
+    <p :class="{ [$style.red]: isRed }">
+      Am I red?
+    </p>
+    <p :class="[$style.red, $style.bold]">
+      Red and bold
+    </p>
+  </div>
+</template>
+

And you can also access it from JavaScript:

<script>
+export default {
+  created () {
+    console.log(this.$style.red)
+    // -> "red_1VyoJ-uZ"
+    // an identifier generated based on filename and className.
+  }
+}
+</script>
+

Refer to the CSS Modules spec for mode details such as global exceptions and composition.

# Opt-in Usage

If you only want to use CSS Modules in some of your Vue components, you can use a oneOf rule and check for the module string in resourceQuery:

// webpack.config.js -> module.rules
+{
+  test: /\.css$/,
+  oneOf: [
+    // this matches `<style module>`
+    {
+      resourceQuery: /module/,
+      use: [
+        'vue-style-loader',
+        {
+          loader: 'css-loader',
+          options: {
+            modules: true,
+            localIdentName: '[local]_[hash:base64:5]'
+          }
+        }
+      ]
+    },
+    // this matches plain `<style>` or `<style scoped>`
+    {
+      use: [
+        'vue-style-loader',
+        'css-loader'
+      ]
+    }
+  ]
+}
+

# Using with Pre-Processors

CSS Modules can be used along with other pre-processors:

// webpack.config.js -> module.rules
+{
+  test: /\.scss$/,
+  use: [
+    'vue-style-loader',
+    {
+      loader: 'css-loader',
+      options: { modules: true }
+    },
+    'sass-loader'
+  ]
+}
+

# Custom Inject Name

You can have more than one <style> tags in a single *.vue component. To avoid injected styles to overwrite each other, you can customize the name of the injected computed property by giving the module attribute a value:

<style module="a">
+  /* identifiers injected as a */
+</style>
+
+<style module="b">
+  /* identifiers injected as b */
+</style>
+
+ + + diff --git a/vue-loader/guide/custom-blocks.html b/vue-loader/guide/custom-blocks.html new file mode 100644 index 000000000..373acde3b --- /dev/null +++ b/vue-loader/guide/custom-blocks.html @@ -0,0 +1,81 @@ + + + + + + Custom Blocks | Vue Loader 中文文档 + + + + + + + +

# Custom Blocks

You can define custom language blocks inside *.vue files. Loaders applied for a custom block are matched based on the lang attribute of the block, the block's tag name, and the rules in your webpack config.

If a lang attribute is specified, the custom block will be matched as a file with the lang as its extension.

You can also use resourceQuery to match a rule against a custom block with no lang. For example, to match against <foo> custom blocks:

{
+  module: {
+    rules: [
+      {
+        resourceQuery: /blockType=foo/,
+        loader: 'loader-to-use'
+      }
+    ]
+  }
+}
+

If a matching rule is found for a custom block, it will be processed; otherwise the custom block will be silently ignored.

Additionally, if the custom block exports a function as the final result after being processed by all the matching loaders, that function will be called with the component of the *.vue file as a parameter.

# Example

Here's an example of injecting the <docs> custom blocks into the component so that it's available during runtime.

In order for the custom block content to be injected, we'll write a custom loader:

module.exports = function (source, map) {
+  this.callback(
+    null,
+    `export default function (Component) {
+      Component.options.__docs = ${
+        JSON.stringify(source)
+      }
+    }`,
+    map
+  )
+}
+

Now we'll configure webpack to use our custom loader for <docs> custom blocks.

// wepback.config.js
+module.exports = {
+  module: {
+    rules: [
+      {
+        resourceQuery: /blockType=docs/,
+        loader: require.resolve('./docs-loader.js')
+      }
+    ]
+  }
+}
+

We are now able to access the <docs> block's content of imported components during runtime.

<!-- ComponentB.vue -->
+<template>
+  <div>Hello</div>
+</template>
+
+<docs>
+This is the documentation for component B.
+</docs>
+
<!-- ComponentA.vue -->
+<template>
+  <div>
+    <ComponentB />
+    <p>{{ docs }}</p>
+  </div>
+</template>
+
+<script>
+import ComponentB from './ComponentB.vue';
+
+export default {
+  components: { ComponentB },
+  data () {
+    return {
+      docs: ComponentB.__docs
+    }
+  }
+}
+</script>
+
+ + + diff --git a/vue-loader/guide/extract-css.html b/vue-loader/guide/extract-css.html new file mode 100644 index 000000000..e3c2bdcd0 --- /dev/null +++ b/vue-loader/guide/extract-css.html @@ -0,0 +1,71 @@ + + + + + + CSS Extraction | Vue Loader 中文文档 + + + + + + + +

# CSS Extraction

TIP

Only apply CSS extraction for production so that you get CSS hot reload during development.

# webpack 4

npm install -D mini-css-extract-plugin
+
// webpack.config.js
+var MiniCssExtractPlugin = require('mini-css-extract-plugin')
+
+module.exports = {
+  // other options...
+  module: {
+    rules: [
+      // ... other rules omitted
+      {
+        test: /\.css$/,
+        use: [
+          process.env.NODE_ENV !== 'production'
+            ? 'vue-style-loader'
+            : MiniCssExtractPlugin.loader,
+          'css-loader'
+        ]
+      }
+    ]
+  },
+  plugins: [
+    // ... Vue Loader plugin omitted
+    new MiniCssExtractPlugin({
+      filename: 'style.css'
+    })
+  ]
+}
+

Also see mini-css-extract-plugin docs.

# webpack 3

npm install -D extract-text-webpack-plugin
+
// webpack.config.js
+var ExtractTextPlugin = require("extract-text-webpack-plugin")
+
+module.exports = {
+  // other options...
+  module: {
+    rules: [
+      // ... other rules omitted
+      {
+        test: /\.css$/,
+        loader: ExtractTextPlugin.extract({
+          use: 'css-loader',
+          fallback: 'vue-style-loader'
+        })
+      }
+    ]
+  },
+  plugins: [
+    // ... Vue Loader plugin omitted
+    new ExtractTextPlugin("style.css")
+  ]
+}
+

Also see extract-text-webpack-plugin docs.

+ + + diff --git a/vue-loader/guide/functional.html b/vue-loader/guide/functional.html new file mode 100644 index 000000000..e5cb1883b --- /dev/null +++ b/vue-loader/guide/functional.html @@ -0,0 +1,27 @@ + + + + + + Functional Components | Vue Loader 中文文档 + + + + + + + +

# Functional Components

Functional components defined as a Single-File Component in a *.vue file also receives proper template compilation, Scoped CSS and hot-reloading support.

To denote a template that should be compiled as a functional component, add the functional attribute to the template block. This also allows omitting the functional option in the <script> block.

Expressions in the template are evaluated in the functional render context. This means props need to be accessed as props.xxx in the template:

<template functional>
+  <div>{{ props.foo }}</div>
+</template>
+

If you need to access properties defined globally on Vue.prototype, you can access them on parent:

<template functional>
+  <div>{{ parent.$someProperty }}</div>
+</template>
+
+ + + diff --git a/vue-loader/guide/hot-reload.html b/vue-loader/guide/hot-reload.html new file mode 100644 index 000000000..ad89269f8 --- /dev/null +++ b/vue-loader/guide/hot-reload.html @@ -0,0 +1,32 @@ + + + + + + Hot Reload | Vue Loader 中文文档 + + + + + + + +

# Hot Reload

"Hot Reload" is not simply reloading the page when you edit a file. With hot reload enabled, when you edit a *.vue file, all instances of that component will be swapped in without reloading the page. It even preserves the current state of your app and these swapped components! This dramatically improves the development experience when you are tweaking the templates or styling of your components.

hot-reload

# State Preservation Rules

  • When editing the <template> of a component, instances of the edited component will re-render in place, preserving all current private state. This is possible because templates are compiled into new render functions that produce no side-effects.

  • When editing the <script> part of a component, instances of the edited component will be destroyed and re-created in place. (State of the other components in the app are preserved) This is because <script> can include lifecycle hooks that may produce side-effects, so a "reload" instead of re-render is required to ensure consistent behavior. This also means you need to be careful about global side effects such as timers inside your components lifecycle hooks. Sometimes you may need to do a full-page reload if your component produces global side-effects.

  • <style> hot reload operates on its own via vue-style-loader, so it doesn't affect application state.

# Usage

When scaffolding the project with vue-cli, Hot Reload is enabled out-of-the-box.

When manually setting up your project, hot-reload is enabled automatically when you serve your project with webpack-dev-server --hot.

Advanced users may want to check out vue-hot-reload-api, which is used internally by vue-loader.

# Disabling Hot Reload

Hot Reload is always enabled except following situations:

  • webpack target is node (SSR)
  • webpack minifies the code
  • process.env.NODE_ENV === 'production'

You may use hotReload: false option to disable the Hot Reload explicitly:

module: {
+  rules: [
+    {
+      test: /\.vue$/,
+      loader: 'vue-loader',
+      options: {
+        hotReload: false // disables Hot Reload
+      }
+    }
+  ]
+}
+
+ + + diff --git a/vue-loader/guide/index.html b/vue-loader/guide/index.html new file mode 100644 index 000000000..f6d1c2141 --- /dev/null +++ b/vue-loader/guide/index.html @@ -0,0 +1,73 @@ + + + + + + Getting Started | Vue Loader 中文文档 + + + + + + + +

# Getting Started

# Vue CLI

If you are not interested in manually setting up webpack, it is recommended to scaffold a project with Vue CLI instead. Projects created by Vue CLI are pre-configured with most of the common development needs working out of the box.

Follow this guide if the built-in configuration of Vue CLI does not suit your needs, or you'd rather create your own webpack config from scratch.

# Manual Setup

# Installation

Unless you are an advanced user using your own forked version of Vue's template compiler, you should install vue-loader and vue-template-compiler together:

npm install -D vue-loader vue-template-compiler
+

The reason vue-template-compiler has to be installed separately is so that you can individually specify its version.

Every time a new version of vue is released, a corresponding version of vue-template-compiler is released together. The compiler's version must be in sync with the base vue package so that vue-loader produces code that is compatible with the runtime. This means every time you upgrade vue in your project, you should upgrade vue-template-compiler to match it as well.

# webpack Configuration

Vue Loader's configuration is a bit different from other loaders. In addition to a rule that applies vue-loader to any files with extension .vue, make sure to add Vue Loader's plugin to your webpack config:

// webpack.config.js
+const VueLoaderPlugin = require('vue-loader/lib/plugin')
+
+module.exports = {
+  module: {
+    rules: [
+      // ... other rules
+      {
+        test: /\.vue$/,
+        loader: 'vue-loader'
+      }
+    ]
+  },
+  plugins: [
+    // make sure to include the plugin!
+    new VueLoaderPlugin()
+  ]
+}
+

The plugin is required! It is responsible for cloning any other rules you have defined and applying them to the corresponding language blocks in .vue files. For example, if you have a rule matching /\.js$/, it will be applied to <script> blocks in .vue files.

A more complete example webpack config will look like this:

// webpack.config.js
+const VueLoaderPlugin = require('vue-loader/lib/plugin')
+
+module.exports = {
+  mode: 'development',
+  module: {
+    rules: [
+      {
+        test: /\.vue$/,
+        loader: 'vue-loader'
+      },
+      // this will apply to both plain `.js` files
+      // AND `<script>` blocks in `.vue` files
+      {
+        test: /\.js$/,
+        loader: 'babel-loader'
+      },
+      // this will apply to both plain `.css` files
+      // AND `<style>` blocks in `.vue` files
+      {
+        test: /\.css$/,
+        use: [
+          'vue-style-loader',
+          'css-loader'
+        ]
+      }
+    ]
+  },
+  plugins: [
+    // make sure to include the plugin for the magic
+    new VueLoaderPlugin()
+  ]
+}
+

Also see Options Reference for all available loader options.

WARNING

If you are developing a library or in a monorepo, please be aware that CSS imports are side effects. Make sure to remove "sideEffects": false in the package.json, otherwise CSS chunks will be dropped by webpack in production builds.

+ + + diff --git a/vue-loader/guide/linting.html b/vue-loader/guide/linting.html new file mode 100644 index 000000000..3d314622d --- /dev/null +++ b/vue-loader/guide/linting.html @@ -0,0 +1,55 @@ + + + + + + Linting | Vue Loader 中文文档 + + + + + + + +

# Linting

# ESLint

The official eslint-plugin-vue supports linting both the template and script parts of Vue single file components.

Make sure to use the plugin's included config in your ESLint config:

// .eslintrc.js
+module.exports = {
+  extends: [
+    "plugin:vue/essential"
+  ]
+}
+

Then from the command line:

eslint --ext js,vue MyComponent.vue
+

Another option is using eslint-loader so that your *.vue files are automatically linted on save during development:

npm install -D eslint eslint-loader
+

Make sure it's applied as a pre-loader:

// webpack.config.js
+module.exports = {
+  // ... other options
+  module: {
+    rules: [
+      {
+        enforce: 'pre',
+        test: /\.(js|vue)$/,
+        loader: 'eslint-loader',
+        exclude: /node_modules/
+      }
+    ]
+  }
+}
+

# stylelint

stylelint supports linting style parts of Vue single file components.

Make sure that your stylelint config is right.

Then from the command line:

stylelint MyComponent.vue
+

Another option is using stylelint-webpack-plugin:

npm install -D stylelint-webpack-plugin
+

Make sure it's applied as a plugin:

// webpack.config.js
+const StyleLintPlugin = require('stylelint-webpack-plugin');
+module.exports = {
+  // ... other options
+  plugins: [
+    new StyleLintPlugin({
+      files: ['**/*.{vue,htm,html,css,sss,less,scss,sass}'],
+    })
+  ]
+}
+
+ + + diff --git a/vue-loader/guide/pre-processors.html b/vue-loader/guide/pre-processors.html new file mode 100644 index 000000000..d1b2e1336 --- /dev/null +++ b/vue-loader/guide/pre-processors.html @@ -0,0 +1,169 @@ + + + + + + Using Pre-Processors | Vue Loader 中文文档 + + + + + + + +

# Using Pre-Processors

In webpack, all pre-processors need to be applied with a corresponding loader. vue-loader allows you to use other webpack loaders to process a part of a Vue component. It will automatically infer the proper loaders to use based on the lang attribute of a language block and the rules in your webpack config.

# Sass

For example, to compile our <style> tag with Sass/SCSS:

npm install -D sass-loader node-sass
+

In your webpack config:

module.exports = {
+  module: {
+    rules: [
+      // ... other rules omitted
+
+      // this will apply to both plain `.scss` files
+      // AND `<style lang="scss">` blocks in `.vue` files
+      {
+        test: /\.scss$/,
+        use: [
+          'vue-style-loader',
+          'css-loader',
+          'sass-loader'
+        ]
+      }
+    ]
+  },
+  // plugin omitted
+}
+

Now in addition to being able to import 'style.scss', we can use SCSS in Vue components as well:

<style lang="scss">
+/* write SCSS here */
+</style>
+

Any content inside the block will be processed by webpack as if it's inside a *.scss file.

# Sass vs SCSS

Note that sass-loader processes the non-indent-based scss syntax by default. In order to use the indent-based sass syntax, you need to pass options to the loader:

// webpack.config.js -> module.rules
+{
+  test: /\.sass$/,
+  use: [
+    'vue-style-loader',
+    'css-loader',
+    {
+      loader: 'sass-loader',
+      options: {
+        indentedSyntax: true,
+        // sass-loader version >= 8
+        sassOptions: {
+          indentedSyntax: true
+        }
+      }
+    }
+  ]
+}
+

# Sharing Global Variables

sass-loader also supports a prependData option which allows you to share common variables among all processed files without having to explicit import them:

// webpack.config.js -> module.rules
+{
+  test: /\.scss$/,
+  use: [
+    'vue-style-loader',
+    'css-loader',
+    {
+      loader: 'sass-loader',
+      options: {
+        // you can also read from a file, e.g. `variables.scss`
+        // use `data` here if sass-loader version < 8
+        prependData: `$color: red;`
+      }
+    }
+  ]
+}
+

# LESS

npm install -D less less-loader
+
// webpack.config.js -> module.rules
+{
+  test: /\.less$/,
+  use: [
+    'vue-style-loader',
+    'css-loader',
+    'less-loader'
+  ]
+}
+

# Stylus

npm install -D stylus stylus-loader
+
// webpack.config.js -> module.rules
+{
+  test: /\.styl(us)?$/,
+  use: [
+    'vue-style-loader',
+    'css-loader',
+    'stylus-loader'
+  ]
+}
+

# PostCSS

TIP

Vue Loader v15 no longer applies PostCSS transforms by default. You will need to use PostCSS via postcss-loader.

npm install -D postcss-loader
+
// webpack.config.js -> module.rules
+{
+  test: /\.css$/,
+  use: [
+    'vue-style-loader',
+    {
+      loader: 'css-loader',
+      options: { importLoaders: 1 }
+    },
+    'postcss-loader'
+  ]
+}
+

Configuration of PostCSS can be done via postcss.config.js or postcss-loader options. For details, consult postcss-loader docs.

postcss-loader can also be applied in combination with other pre-processors mentioned above.

# Babel

npm install -D babel-core babel-loader
+
// webpack.config.js -> module.rules
+{
+  test: /\.js?$/,
+  loader: 'babel-loader'
+}
+

Configuration of Babel can be done via .babelrc or babel-loader options.

# Excluding node_modules

It is common to have exclude: /node_modules/ for JS transpilation rules (e.g. babel-loader) that apply to .js files. Due to the inference change of v15, if you import a Vue SFC inside node_modules, its <script> part will be excluded from transpilation as well.

In order to ensure JS transpilation is applied to Vue SFCs in node_modules, you need to whitelist them by using an exclude function instead:

{
+  test: /\.js$/,
+  loader: 'babel-loader',
+  exclude: file => (
+    /node_modules/.test(file) &&
+    !/\.vue\.js/.test(file)
+  )
+}
+

# TypeScript

npm install -D typescript ts-loader
+
// webpack.config.js
+module.exports = {
+  resolve: {
+    // Add `.ts` as a resolvable extension.
+    extensions: ['.ts', '.js']
+  },
+  module: {
+    rules: [
+      // ... other rules omitted
+      {
+        test: /\.ts$/,
+        loader: 'ts-loader',
+        options: { appendTsSuffixTo: [/\.vue$/] }
+      }
+    ]
+  },
+  // ... plugin omitted
+}
+

Configuration of TypeScipt can be done via tsconfig.json. Also see docs for ts-loader.

# Pug

Processing templates is a little different, because most webpack template loaders such as pug-loader return a template function instead of a compiled HTML string. Instead of using pug-loader, we need to use a loader that returns the raw HTML string, e.g. pug-plain-loader:

npm install -D pug pug-plain-loader
+
// webpack.config.js -> module.rules
+{
+  test: /\.pug$/,
+  loader: 'pug-plain-loader'
+}
+

Then you can write:

<template lang="pug">
+div
+  h1 Hello world!
+</template>
+

If you also intend to use it to import .pug files as HTML strings in JavaScript, you will need to chain raw-loader after the preprocessing loader. Note however adding raw-loader would break the usage in Vue components, so you need to have two rules, one of them targeting Vue files using a resourceQuery, the other one (fallback) targeting JavaScript imports:

// webpack.config.js -> module.rules
+{
+  test: /\.pug$/,
+  oneOf: [
+    // this applies to `<template lang="pug">` in Vue components
+    {
+      resourceQuery: /^\?vue/,
+      use: ['pug-plain-loader']
+    },
+    // this applies to pug imports inside JavaScript
+    {
+      use: ['raw-loader', 'pug-plain-loader']
+    }
+  ]
+}
+
+ + + diff --git a/vue-loader/guide/scoped-css.html b/vue-loader/guide/scoped-css.html new file mode 100644 index 000000000..f95893e0a --- /dev/null +++ b/vue-loader/guide/scoped-css.html @@ -0,0 +1,50 @@ + + + + + + Scoped CSS | Vue Loader 中文文档 + + + + + + + +

# Scoped CSS

When a <style> tag has the scoped attribute, its CSS will apply to elements of the current component only. This is similar to the style encapsulation found in Shadow DOM. It comes with some caveats, but doesn't require any polyfills. It is achieved by using PostCSS to transform the following:

<style scoped>
+.example {
+  color: red;
+}
+</style>
+
+<template>
+  <div class="example">hi</div>
+</template>
+

Into the following:

<style>
+.example[data-v-f3f3eg9] {
+  color: red;
+}
+</style>
+
+<template>
+  <div class="example" data-v-f3f3eg9>hi</div>
+</template>
+

# Mixing Local and Global Styles

You can include both scoped and non-scoped styles in the same component:

<style>
+/* global styles */
+</style>
+
+<style scoped>
+/* local styles */
+</style>
+

# Child Component Root Elements

With scoped, the parent component's styles will not leak into child components. However, a child component's root node will be affected by both the parent's scoped CSS and the child's scoped CSS. This is by design so that the parent can style the child root element for layout purposes.

# Deep Selectors

If you want a selector in scoped styles to be "deep", i.e. affecting child components, you can use the >>> combinator:

<style scoped>
+.a >>> .b { /* ... */ }
+</style>
+

The above will be compiled into:

.a[data-v-f3f3eg9] .b { /* ... */ }
+

Some pre-processors, such as Sass, may not be able to parse >>> properly. In those cases you can use the /deep/ or ::v-deep combinator instead - both are aliases for >>> and work exactly the same.

# Dynamically Generated Content

DOM content created with v-html are not affected by scoped styles, but you can still style them using deep selectors.

# Also Keep in Mind

  • Scoped styles do not eliminate the need for classes. Due to the way browsers render various CSS selectors, p { color: red } will be many times slower when scoped (i.e. when combined with an attribute selector). If you use classes or ids instead, such as in .example { color: red }, then you virtually eliminate that performance hit.

  • Be careful with descendant selectors in recursive components! For a CSS rule with the selector .a .b, if the element that matches .a contains a recursive child component, then all .b in that child component will be matched by the rule.

+ + + diff --git a/vue-loader/guide/testing.html b/vue-loader/guide/testing.html new file mode 100644 index 000000000..1b32e9b96 --- /dev/null +++ b/vue-loader/guide/testing.html @@ -0,0 +1,21 @@ + + + + + + Testing | Vue Loader 中文文档 + + + + + + + +

# Testing

  • Vue CLI offers pre-configured unit testing and e2e testing setups.

  • If you are interested in manually setting up unit tests for *.vue files, consult the docs for @vue/test-utils, which covers setup with mocha-webpack or Jest.

+ + + diff --git a/vue-loader/hot-reload.gif b/vue-loader/hot-reload.gif new file mode 100644 index 000000000..35a4324a5 Binary files /dev/null and b/vue-loader/hot-reload.gif differ diff --git a/vue-loader/index.html b/vue-loader/index.html new file mode 100644 index 000000000..f20ec78ae --- /dev/null +++ b/vue-loader/index.html @@ -0,0 +1,40 @@ + + + + + + Introduction | Vue Loader 中文文档 + + + + + + + +

# Introduction

VERSION NOTE

This is the documentation for Vue Loader v15 and above. If you are upgrading from v14 or an earlier version, check out the Migration Guide. If you are using an older version, the old docs are here.

# What is Vue Loader?

vue-loader is a loader for webpack that allows you to author Vue components in a format called Single-File Components (SFCs):

<template>
+  <div class="example">{{ msg }}</div>
+</template>
+
+<script>
+export default {
+  data () {
+    return {
+      msg: 'Hello world!'
+    }
+  }
+}
+</script>
+
+<style>
+.example {
+  color: red;
+}
+</style>
+

There are many cool features provided by vue-loader:

  • Allows using other webpack loaders for each part of a Vue component, for example Sass for <style> and Pug for <template>;
  • Allows custom blocks in a .vue file that can have custom loader chains applied to them;
  • Treat static assets referenced in <style> and <template> as module dependencies and handle them with webpack loaders;
  • Simulate scoped CSS for each component;
  • State-preserving hot-reloading during development.

In a nutshell, the combination of webpack and vue-loader gives you a modern, flexible and extremely powerful front-end workflow for authoring Vue.js applications.

+ + + diff --git a/vue-loader/migrating.html b/vue-loader/migrating.html new file mode 100644 index 000000000..edd283943 --- /dev/null +++ b/vue-loader/migrating.html @@ -0,0 +1,160 @@ + + + + + + Migrating from v14 | Vue Loader 中文文档 + + + + + + + +

# Migrating from v14

Heads Up

We are in the process of upgrading Vue CLI 3 beta to use webpack 4 + Vue Loader v15, so you might want to wait if you are planning to upgrade to Vue CLI 3.

# Notable Breaking Changes

# A Plugin is Now Required

Vue Loader v15 now requires an accompanying webpack plugin to function properly:

// webpack.config.js
+const VueLoaderPlugin = require('vue-loader/lib/plugin')
+
+module.exports = {
+  // ...
+  plugins: [
+    new VueLoaderPlugin()
+  ]
+}
+

# Loader Inference

Vue Loader v15 now uses a different strategy to infer loaders to use for language blocks.

Take <style lang="less"> as an example: in v14 and below, it will attempt to load the block with less-loader, and implicitly chains css-loader and vue-style-loader after it, all using inline loader strings.

In v15, <style lang="less"> will behave as if it's an actual *.less file being loaded. So, in order to process it, you need to provide an explicit rule in your main webpack config:

{
+  module: {
+    rules: [
+      // ... other rules
+      {
+        test: /\.less$/,
+        use: [
+          'vue-style-loader',
+          'css-loader',
+          'less-loader'
+        ]
+      }
+    ]
+  }
+}
+

The benefit is that this same rule also applies to plain *.less imports from JavaScript, and you can configure options for these loaders anyway you want. In v14 and below, if you want to provide custom options to an inferred loader, you'd have to duplicate it under Vue Loader's own loaders option. In v15 it is no longer necessary.

v15 also allows using non-serializable options for loaders, which was not possible in previous versions.

# Importing SFCs from Dependencies

It is common to have exclude: /node_modules/ for JS transpilation rules (e.g. babel-loader) that apply to .js files. Due to the inference change of v15, if you import a Vue SFC inside node_modules, its <script> part will be excluded from transpilation as well.

In order to ensure JS transpilation is applied to Vue SFCs in node_modules, you need to whitelist them by using an exclude function instead:

{
+  test: /\.js$/,
+  loader: 'babel-loader',
+  exclude: file => (
+    /node_modules/.test(file) &&
+    !/\.vue\.js/.test(file)
+  )
+}
+

# Template Preprocessing

v14 and below uses consolidate to compile <template lang="xxx">. v15 now applies preprocessing for them using webpack loaders instead.

Note that some template loaders such as pug-loader exports a compiled templating function instead of plain HTML. In order to pass the correct content to Vue's template compiler, you must use a loader that outputs plain HTML instead. For example, to support <template lang="pug">, you can use pug-plain-loader:

{
+  module: {
+    rules: [
+      {
+        test: /\.pug$/,
+        loader: 'pug-plain-loader'
+      }
+    ]
+  }
+}
+

If you also intend to use it to import .pug files as HTML strings in JavaScript, you will need to chain raw-loader after the preprocessing loader. Note however adding raw-loader would break the usage in Vue components, so you need to have two rules, one of them targeting Vue files using a resourceQuery, the other one (fallback) targeting JavaScript imports:

{
+  module: {
+    rules: [
+      {
+        test: /\.pug$/,
+        oneOf: [
+          // this applies to `<template lang="pug">` in Vue components
+          {
+            resourceQuery: /^\?vue/,
+            use: ['pug-plain-loader']
+          },
+          // this applies to pug imports inside JavaScript
+          {
+            use: ['raw-loader', 'pug-plain-loader']
+          }
+        ]
+      }
+    ]
+  }
+}
+

# Style Injection

Client-side style injection now injects all styles upfront to ensure consistent behavior between development and extracted mode.

Note the injection order is still not guaranteed, so you should avoid writing CSS that relies on insertion order.

# PostCSS

Vue Loader no longer auto applies PostCSS transforms. To use PostCSS, configure postcss-loader the same way you would for normal CSS files.

# CSS Modules

CSS Modules now need to be explicitly configured via css-loader options. The module attribute on <style> tags is still needed for locals injection into the component.

The good news is that you can now configure localIdentName in one place:

{
+  module: {
+    rules: [
+      {
+        test: /\.css$/,
+        use: [
+          {
+            loader: 'vue-style-loader'
+          },
+          {
+            loader: 'css-loader',
+            options: {
+              modules: true,
+              localIdentName: '[local]_[hash:base64:8]'
+            }
+          }
+        ]
+      }
+    ]
+  }
+}
+

If you only want to use CSS Modules in some of your Vue components, you can use a oneOf rule and check for the module string in resourceQuery:

{
+  test: /\.css$/,
+  oneOf: [
+    // this matches `<style module>`
+    {
+      resourceQuery: /module/,
+      use: [
+        'vue-style-loader',
+        {
+          loader: 'css-loader',
+          options: {
+            modules: true,
+            localIdentName: '[local]_[hash:base64:5]'
+          }
+        }
+      ]
+    },
+    // this matches plain `<style>` or `<style scoped>`
+    {
+      use: [
+        'vue-style-loader',
+        'css-loader'
+      ]
+    }
+  ]
+}
+

# CSS Extraction

Works the same way as you'd configure it for normal CSS. Example usage with mini-css-extract-plugin:

{
+  module: {
+    rules: [
+      {
+        test: /\.vue$/,
+        use: 'vue-loader'
+      },
+      {
+        test: /\.css$/,
+        // or `ExtractTextWebpackPlugin.extract(...)`
+        use: [
+          MiniCssExtractPlugin.loader,
+          'css-loader'
+        ]
+      }
+    ]
+  },
+  plugins: [
+    new MiniCssExtractPlugin({
+      filename: 'output.css'
+    })
+  ]
+}
+

# SSR externals

In SSR, we typically use webpack-node-externals to exclude npm dependencies from the server build. If you need to import CSS from an npm dependency, the previous solution was using a whitelist like this:

// webpack config
+externals: nodeExternals({
+  whitelist: /\.css$/
+})
+

With v15, imports for <style src="dep/foo.css"> now has resourceQuery strings appended at the end of the request, so you need to update the above to:

externals: nodeExternals({
+  whitelist: [/\.css$/, /\?vue&type=style/]
+})
+

# Options Deprecation

The following options have been deprecated and should be configured using normal webpack module rules:

  • loader
  • preLoaders
  • postLoaders
  • postcss
  • cssSourceMap
  • buble
  • extractCSS
  • template

The following options have been deprecated and should be configured using the new compilerOptions option:

  • preserveWhitespace (use compilerOptions.preserveWhitespace)
  • compilerModules (use compilerOptions.modules)
  • compilerDirectives (use compilerOptions.directives)

The following option has been renamed:

  • transformToRequire (now renamed to transformAssetUrls)

TIP

For a complete list of new options, see Options Reference.

+ + + diff --git a/vue-loader/options.html b/vue-loader/options.html new file mode 100644 index 000000000..a901221a2 --- /dev/null +++ b/vue-loader/options.html @@ -0,0 +1,29 @@ + + + + + + Options Reference | Vue Loader 中文文档 + + + + + + + +

# Options Reference

# transformAssetUrls

  • type: { [tag: string]: string | Array<string> }

  • default:

    {
    +  video: ['src', 'poster'],
    +  source: 'src',
    +  img: 'src',
    +  image: ['xlink:href', 'href'],
    +  use: ['xlink:href', 'href']
    +}
    +

    During template compilation, the compiler can transform certain attributes, such as src URLs, into require calls, so that the target asset can be handled by webpack. For example, <img src="./foo.png"> will attempt to locate the file ./foo.png on your file system and include it as a dependency of your bundle.

# compiler

  • Type: VueTemplateCompiler

  • default: require('vue-template-compiler')

    Override the default compiler used to compile <template> blocks in single file components.

# compilerOptions

  • type: Object

  • default: {}

    Options for the template compiler. When using the default vue-template-compiler, you can use this option to add custom compiler directives, modules, or discard whitespaces between template tags with { preserveWhitespace: false }.

    See vue-template-compiler options reference.

# transpileOptions

  • type: Object

  • default: {}

    Configure ES2015+ to ES5 transpiling options for the generated render function code. The transpiler is a fork of Buble, so consult the available options here.

    The template render functions compilation supports a special transform stripWith (enabled by default), which removes the with usage in generated render functions to make them strict-mode compliant.

# optimizeSSR

  • type: boolean

  • default: true when the webpack config has target: 'node' and vue-template-compiler is at version 2.4.0 or above.

    Enable Vue 2.4 SSR compilation optimization that compiles part of the vdom trees returned by render functions into plain strings, which improves SSR performance. In some cases you might want to explicitly turn it off because the resulting render functions can only be used for SSR and cannot be used for client-side rendering or testing.

# hotReload

  • type: boolean

  • default: true in development mode, false in production mode or when the webpack config has target: 'node'.

  • allowed value: false (true will not force Hot Reload neither in production mode nor when target: 'node')

    Whether to use webpack Hot Module Replacement to apply changes in the browser without reloading the page. +Use this option (value false) to disable the Hot Reload feature in development mode.

# productionMode

  • type: boolean
  • default: process.env.NODE_ENV === 'production'

Force production mode, which prohibits the loader from emitting code (e.g. hot-reload related code) that is development-only.

# shadowMode

  • type: boolean
  • default: false

Compiled the component for usage inside Shadow DOM. In this mode, the styles of the component will be injected into this.$root.$options.shadowRoot instead of the document head.

# cacheDirectory / cacheIdentifier

  • type: string
  • default: undefined

When both options are specified, enables file-system-based template compilation caching (requires cache-loader to be installed in the same project).

TIP

Interaction between vue-loader and cache-loader uses inline loader import syntax under the hook, the ! will be treated as the separator between different loaders, so please ensure cacheDirectory doesn't contain !.

# prettify

  • type: boolean
  • default: true

In development mode, we use prettier to format the compiled render function for ease of debugging by default. However, if you encounter any obscure bug of prettier, such as exponential compilation time for deeply nested functions, you can disable this option to circumvent it.

# exposeFilename

  • type: boolean
  • default: false

In non-production environments, vue-loader injects a __file property to components for better debugging experience. If the name property is missing in a component, Vue will infer it from the __file field to display in console warnings.

This property is stripped in production builds by default. But you may want to retain it if you are developing a component library and don't want to bother specifying name in each component. Then you can turn this option on.

+ + + diff --git a/vue-loader/ru/guide/asset-url.html b/vue-loader/ru/guide/asset-url.html new file mode 100644 index 000000000..c9e5f9843 --- /dev/null +++ b/vue-loader/ru/guide/asset-url.html @@ -0,0 +1,43 @@ + + + + + + Обработка вложенных URL | Vue Loader + + + + + + + +

# Обработка вложенных URL

Когда Vue Loader компилирует секции <template> в однофайловых компонентах, то он будет трактовать все использованные URL как зависимости модуля.

Например, следующий примера шаблона:

<img src="../image.png">
+

будет скомпилирован в:

createElement('img', {
+  attrs: {
+    src: require('../image.png') // теперь это запрос к модулю
+  }
+})
+

По умолчанию следующие комбинации тегов/атрибутов преобразуются и могут быть настроены с помощью опции transformAssetUrls.

{
+  video: ['src', 'poster'],
+  source: 'src',
+  img: 'src',
+  image: ['xlink:href', 'href'],
+  use: ['xlink:href', 'href']
+}
+

Кроме того, если вы настроили использование css-loader для секций <style>, используемые URL-адреса в вашем CSS будут обрабатываться аналогичным образом.

# Правила преобразования

Преобразования URL ресурсов подчиняются следующим правилам:

  • Если в URL абсолютный путь (например, /images/foo.png), он будет оставлен как есть.

  • Если URL начинается с ., он будет истолковываться как запрос модуля относительно текущего каталога и разрешаться на основе структуры каталогов вашей файловой системы.

  • Если URL начинается с ~, то всё что после него будет истолковываться как запрос модуля. Это означает, что вы можете ссылаться на ресурсы даже внутри node_modules:

    <img src="~some-npm-package/foo.png">
    +
  • Если URL начинается с @, то также будет истолковываться как запрос модуля. Это полезно если в вашей конфигурации webpack есть псевдоним для @, который по умолчанию указывает на /src в любом проекте, созданном через vue-cli.

# Связанные загрузчики

Так как файлы с расширениями, таким как .png, не являются JavaScript- модулями, вам необходимо настроить webpack для использования file-loader или url-loader чтобы корректно их обрабатывать. Проекты создаваемые с помощью Vue CLI уже предварительно настраивают это для вас.

# Почему так

Преимущества подобных преобразований URL:

  1. file-loader позволяет определить куда нужно скопировать и поместить файл, а также как именовать его, добавляя в имя хэш для лучшего кеширования. Кроме того, это означает что вы можете просто поместить изображения рядом с вашим *.vue файлами и использовать относительные пути, основанные на структуре каталогов, не беспокоясь об адресах при публикации. При правильной конфигурации, webpack будет автоматически заменять пути к файлам на корректные URL в итоговой сборке.

  2. url-loader позволяет вставлять файлы как base-64 ссылки, если они меньше указанного размера. Это позволит уменьшить количество HTTP-запросов при использовании маленьких файлов. Если же файл больше указанного порога, то он автоматически подключится с помощью file-loader.

+ + + diff --git a/vue-loader/ru/guide/css-modules.html b/vue-loader/ru/guide/css-modules.html new file mode 100644 index 000000000..e48bebee4 --- /dev/null +++ b/vue-loader/ru/guide/css-modules.html @@ -0,0 +1,130 @@ + + + + + + CSS модули | Vue Loader + + + + + + + +

# CSS модули

CSS модули — это популярная система для модульности и компоновки CSS. vue-loader предоставляет первоклассную интеграцию с CSS модулями как возможную альтернативу эмулируемого локального (scoped) CSS.

# Использование

Во-первых, CSS модули нужно явно включить, передав опцию modules: true в css-loader:

// webpack.config.js
+{
+  module: {
+    rules: [
+      // ... другие правила опущены
+      {
+        test: /\.css$/,
+        use: [
+          'vue-style-loader',
+          {
+            loader: 'css-loader',
+            options: {
+              // включаем CSS модули
+              modules: true,
+              // настраиваем генерируемое имя класса
+              localIdentName: '[local]_[hash:base64:8]'
+            }
+          }
+        ]
+      }
+    ]
+  }
+}
+

Затем, добавляем атрибут module к тегу секции <style>:

<style module>
+.red {
+  color: red;
+}
+.bold {
+  font-weight: bold;
+}
+</style>
+

Атрибут module подскажет Vue Loader о необходимости внедрить CSS модуль в компонент в качестве вычисляемого свойства с именем $style. Вы можете использовать его в шаблонах для динамического добавления классов:

<template>
+  <p :class="$style.red">
+    Текст должен быть красным
+  </p>
+</template>
+

Поскольку это вычисляемое свойство, оно будет работать с объектом/массивом в :class:

<template>
+  <div>
+    <p :class="{ [$style.red]: isRed }">
+      Буду ли я красным?
+    </p>
+    <p :class="[$style.red, $style.bold]">
+      Красный и жирный
+    </p>
+  </div>
+</template>
+

Вы также можете получить доступ в JavaScript:

<script>
+export default {
+  created () {
+    console.log(this.$style.red)
+    // -> "red_1VyoJ-uZ"
+    // идентификатор генерируется на основе имени файла и className.
+  }
+}
+</script>
+

Обратитесь к спецификации CSS-модулей для получения информации о глобальных исключениях и композиции.

# Опциональное использование

Если вы хотите использовать CSS модули только в некоторых компонентах Vue, вы можете использовать правило oneOf и проверять наличие строки module внутри resourceQuery:

// webpack.config.js -> module.rules
+{
+  test: /\.css$/,
+  oneOf: [
+    // это соответствует `<style module>`
+    {
+      resourceQuery: /module/,
+      use: [
+        'vue-style-loader',
+        {
+          loader: 'css-loader',
+          options: {
+            modules: true,
+            localIdentName: '[local]_[hash:base64:5]'
+          }
+        }
+      ]
+    },
+    // это соответствует простому `<style>` или `<style scoped>`
+    {
+      use: [
+        'vue-style-loader',
+        'css-loader'
+      ]
+    }
+  ]
+}
+

# Использование с пре-процессорами

CSS модули могут быть использованы вместе с другими пре-процессорами:

// webpack.config.js -> module.rules
+{
+  test: /\.scss$/,
+  use: [
+    'vue-style-loader',
+    {
+      loader: 'css-loader',
+      options: { modules: true }
+    },
+    'sass-loader'
+  ]
+}
+

# Указание имени внедряемого модуля

У вас может быть несколько тегов <style> в одном компоненте *.vue. Во избежание перезаписи внедряемых стилей вы можете указать имя внедряемого вычисляемого свойства в значении атрибута module:

<style module="a">
+  /* идентификатор будет внедрён как a */
+</style>
+
+<style module="b">
+  /* идентификатор будет внедрён как b */
+</style>
+
+ + + diff --git a/vue-loader/ru/guide/custom-blocks.html b/vue-loader/ru/guide/custom-blocks.html new file mode 100644 index 000000000..d80aa8f85 --- /dev/null +++ b/vue-loader/ru/guide/custom-blocks.html @@ -0,0 +1,87 @@ + + + + + + Пользовательские блоки | Vue Loader + + + + + + + +

# Пользовательские блоки

Вы можете определять пользовательские блоки внутри файлов *.vue. Загрузчики, применяемые к такому блоку, будут определяться сопоставлением по атрибуту lang блока, имени тега блока, и правил в вашей конфигурации webpack.

Если указан атрибут lang, пользовательский блок будет обработан как файл с расширением, указанном в lang.

Вы также можете использовать resourceQuery для определения правила для блока без атрибута lang. Например, для сопоставления пользовательского блока <foo>:

{
+  module: {
+    rules: [
+      {
+        resourceQuery: /blockType=foo/,
+        loader: "loader-to-use"
+      }
+    ];
+  }
+}
+

Если для пользовательского блока будет найдено правило — он будет им обработан; в противном случае пользовательский блок будет тихо проигнорирован.

Кроме того, если пользовательский блок экспортирует функцию в качестве конечного результата после обработки всеми соответствующими загрузчиками, то эта функция будет вызываться с компонентом файла *.vue в качестве параметра.

# Пример

Небольшой пример внедрения пользовательского блока <docs> в компонент таким образом, что он будет доступен во время выполнения.

Для внедрения содержимого пользовательского блока мы напишем собственный загрузчик:

module.exports = function(source, map) {
+  this.callback(
+    null,
+    `export default function (Component) {
+      Component.options.__docs = ${JSON.stringify(source)}
+    }`,
+    map
+  );
+};
+

Настроим webpack использовать наш загрузчик для пользовательских блоков <docs>.

// wepback.config.js
+module.exports = {
+  module: {
+    rules: [
+      {
+        resourceQuery: /blockType=docs/,
+        loader: require.resolve("./docs-loader.js")
+      }
+    ]
+  }
+};
+

Теперь мы можем получить доступ к содержимому блока <docs> импортированного компонента на этапе выполнения.

<!-- ComponentB.vue -->
+<template>
+  <div>Hello</div>
+</template>
+
+<docs>
+This is the documentation for component B.
+</docs>
+
<!-- ComponentA.vue -->
+<template>
+  <div>
+    <ComponentB />
+    <p>{{ docs }}</p>
+  </div>
+</template>
+
+<script>
+import ComponentB from "./ComponentB.vue";
+
+export default {
+  components: { ComponentB },
+  data() {
+    return {
+      docs: ComponentB.__docs
+    };
+  }
+};
+</script>
+
+ + + diff --git a/vue-loader/ru/guide/extract-css.html b/vue-loader/ru/guide/extract-css.html new file mode 100644 index 000000000..b691b8c24 --- /dev/null +++ b/vue-loader/ru/guide/extract-css.html @@ -0,0 +1,79 @@ + + + + + + Извлечение CSS в отдельный файл | Vue Loader + + + + + + + +

# Извлечение CSS в отдельный файл

СОВЕТ

Применяйте извлечение CSS в отдельный файл только в production, чтобы использовать горячую перезагрузку CSS на этапе разработки.

# webpack 4

npm install -D mini-css-extract-plugin
+
// webpack.config.js
+var MiniCssExtractPlugin = require('mini-css-extract-plugin')
+
+module.exports = {
+  // другие настройки...
+  module: {
+    rules: [
+      // ... другие правила опущены
+      {
+        test: /\.css$/,
+        use: [
+          process.env.NODE_ENV !== 'production'
+            ? 'vue-style-loader'
+            : MiniCssExtractPlugin.loader,
+          'css-loader'
+        ]
+      }
+    ]
+  },
+  plugins: [
+    // ... плагин Vue Loader опущен
+    new MiniCssExtractPlugin({
+      filename: 'style.css'
+    })
+  ]
+}
+

Также смотрите документацию mini-css-extract-plugin.

# webpack 3

npm install -D extract-text-webpack-plugin
+
// webpack.config.js
+var ExtractTextPlugin = require("extract-text-webpack-plugin")
+
+module.exports = {
+  // другие настройки...
+  module: {
+    rules: [
+      // ... другие правила опущены
+      {
+        test: /\.css$/,
+        loader: ExtractTextPlugin.extract({
+          use: 'css-loader',
+          fallback: 'vue-style-loader'
+        })
+      }
+    ]
+  },
+  plugins: [
+    // ... плагин Vue Loader опущен
+    new ExtractTextPlugin("style.css")
+  ]
+}
+

Также смотрите документацию extract-text-webpack-plugin.

+ + + diff --git a/vue-loader/ru/guide/functional.html b/vue-loader/ru/guide/functional.html new file mode 100644 index 000000000..9d92202bf --- /dev/null +++ b/vue-loader/ru/guide/functional.html @@ -0,0 +1,35 @@ + + + + + + Функциональные компоненты | Vue Loader + + + + + + + +

# Функциональные компоненты

Функциональные компоненты, объявленные как однофайловые компоненты в файле *.vue, также получают правильную поддержку компиляции шаблона, локальный CSS и поддержку горячей перезагрузки.

Чтобы обозначить шаблон, который должен быть скомпилирован как функциональный компонент, добавьте атрибут functional в тег шаблона. Это также позволяет опустить опцию functional в теге <script>.

Выражения в шаблоне исполняются в контексте функционального рендеринга. Это означает, что обращаться к входным параметрам в шаблоне следует через props.xxx:

<template functional>
+  <div>{{ props.foo }}</div>
+</template>
+

Если вам необходимо получить доступ к свойствам, определённым глобально в Vue.prototype, вы можете получить к ним доступ через parent:

<template functional>
+  <div>{{ parent.$someProperty }}</div>
+</template>
+
+ + + diff --git a/vue-loader/ru/guide/hot-reload.html b/vue-loader/ru/guide/hot-reload.html new file mode 100644 index 000000000..db8fbf745 --- /dev/null +++ b/vue-loader/ru/guide/hot-reload.html @@ -0,0 +1,40 @@ + + + + + + Горячая перезагрузка | Vue Loader + + + + + + + +

# Горячая перезагрузка

"Горячая перезагрузка" это не просто обновление страницы, когда вы отредактируете файл. При использовании горячей перезагрузки, когда вы отредактируете *.vue файл, все экземпляры этого компонента будут заменены без перезагрузки страницы. При этом даже будет сохранено текущее состояние вашего приложения и заменяемых компонентов! Это значительно улучшает процесс разработки, особенно когда вы занимаетесь тонкой настройкой шаблонов или стилей ваших компонентов.

hot-reload

# Правила сохранения состояния

  • При редактировании <template> компонента, экземпляры изменённого компонента будут повторно отрендерены, сохраняя всё текущее собственное состояние. Это возможно, потому что шаблоны компилируются в новые render-функции, которые не создают побочных эффектов.

  • При редактировании <script> компонента, экземпляры редактируемого компонента будут уничтожены и созданы заново (состояние других компонентов в приложении сохраняется). Это связано с тем, что <script> может включать в себя хуки жизненного цикла, которые могут создавать побочные эффекты, поэтому для обеспечения согласованности поведения требуется "перезагрузка", а не просто повторный рендеринг. Это также означает, что вам нужно быть осторожным в отношении глобальных побочных эффектов, например использования таймеров внутри хуков жизненного цикла компонентов. Иногда вам может потребоваться полная перезагрузка страницы, если ваш компонент создаёт глобальные побочные эффекты.

  • Горячая перезагрузка <style> работает самостоятельно через vue-style-loader, поэтому никак не затрагивает состояние приложения.

# Использование

При создании проекта с помощью vue-cli, горячая перезагрузка включена по умолчанию.

При настройке проекта вручную горячая перезагрузка включится автоматически, когда вы запускаете ваш проект с помощью webpack-dev-server --hot.

Продвинутые пользователи могут изучить vue-hot-reload-api, который используется внутри vue-loader.

# Отключение горячей перезагрузки

Горячая перезагрузка всегда включена, за исключением следующих ситуаций:

  • опция webpack target в значении node (SSR)
  • webpack минифицирует код
  • process.env.NODE_ENV === 'production'

Вы можете использовать опцию hotReload: false для принудительного выключения горячей перезагрузки:

module: {
+  rules: [
+    {
+      test: /\.vue$/,
+      loader: 'vue-loader',
+      options: {
+        hotReload: false // отключает горячую перезагрузку
+      }
+    }
+  ]
+}
+
+ + + diff --git a/vue-loader/ru/guide/index.html b/vue-loader/ru/guide/index.html new file mode 100644 index 000000000..abfc7061e --- /dev/null +++ b/vue-loader/ru/guide/index.html @@ -0,0 +1,81 @@ + + + + + + Начало работы | Vue Loader + + + + + + + +

# Начало работы

# Vue CLI

Если вы не заинтересованы настраивать вручную webpack, тогда мы рекомендуем вам разворачивать проекты с помощью Vue CLI. Проекты создаваемые с помощью Vue CLI предварительно сконфигурированы с учётом большинства общих потребностей при разработке из коробки.

Следуйте этому руководству, если встроенная конфигурация Vue CLI не подходит для ваших нужд, или вы предпочитаете создавать собственную конфигурацию webpack с нуля.

# Настройка вручную

# Установка

Если вы не продвинутый пользователь, использующий собственную форкнутую версию компилятора шаблонов Vue, то должны установить vue-loader и vue-template-compiler вместе:

npm install -D vue-loader vue-template-compiler
+

Причина, по которой vue-template-compiler требуется устанавливать отдельно в том, что можно отдельно указать его версию.

Каждый раз, когда выходит новая версия vue, выпускается и соответствующая версия vue-template-compiler. Версия компилятора должна быть аналогичной версии базового пакета vue, чтобы vue-loader генерировал код совместимый с runtime. Поэтому каждый раз, когда вы обновляете vue в проекте, вы должны также обновить и vue-template-compiler до такой же версии.

# Конфигурация webpack

Конфигурация Vue Loader немного отличается от настройки других загрузчиков. В дополнении к правилу, которое будет применять vue-loader ко всем файлам с расширением .vue, убедитесь что добавили плагин Vue Loader в вашу конфигурацию webpack:

// webpack.config.js
+const VueLoaderPlugin = require('vue-loader/lib/plugin')
+
+module.exports = {
+  module: {
+    rules: [
+      // ... другие правила
+      {
+        test: /\.vue$/,
+        loader: 'vue-loader'
+      }
+    ]
+  },
+  plugins: [
+    // убедитесь что подключили плагин!
+    new VueLoaderPlugin()
+  ]
+}
+

Плагин необходим! Он отвечает за клонирование любых других правил, которые вы определили, чтобы применить их к соответствующим языковым блокам в файлах .vue. Например, если у вас есть правило, соответствующее файлам /\.js$/, оно будет применяться к секциям <script> в файлах .vue.

Более полная версия конфигурации webpack будет выглядеть так:

// webpack.config.js
+const VueLoaderPlugin = require('vue-loader/lib/plugin')
+
+module.exports = {
+  mode: 'development',
+  module: {
+    rules: [
+      {
+        test: /\.vue$/,
+        loader: 'vue-loader'
+      },
+      // это будет применяться к файлам `.js`
+      // А ТАКЖЕ к секциям `<script>` внутри файлов `.vue`
+      {
+        test: /\.js$/,
+        loader: 'babel-loader'
+      },
+      // это будет применяться к файлам `.css`
+      // А ТАКЖЕ к секциям `<style>` внутри файлов `.vue`
+      {
+        test: /\.css$/,
+        use: [
+          'vue-style-loader',
+          'css-loader'
+        ]
+      }
+    ]
+  },
+  plugins: [
+    // убедитесь что подключили плагин!
+    new VueLoaderPlugin()
+  ]
+}
+

Также смотрите перечень настроек, где перечислены все доступные опции загрузчика.

ВНИМАНИЕ

При разработке библиотеки или работе в монорепозитории, имейте ввиду, что импорты CSS являются сайд-эффектами. Убедитесь, что удалили "sideEffects": false в package.json, в противном случае фрагменты CSS будут удалены webpack в сборках для production.

+ + + diff --git a/vue-loader/ru/guide/linting.html b/vue-loader/ru/guide/linting.html new file mode 100644 index 000000000..86fd30846 --- /dev/null +++ b/vue-loader/ru/guide/linting.html @@ -0,0 +1,63 @@ + + + + + + Статический анализ кода | Vue Loader + + + + + + + +

# Статический анализ кода

# ESLint

Официальный плагин eslint-plugin-vue поддерживает проверку секций шаблона и кода в однофайловых компонентах Vue.

Убедитесь, что используете поставляемую с плагином конфигурацию в вашей конфигурации ESLint:

// .eslintrc.js
+module.exports = {
+  extends: [
+    "plugin:vue/essential"
+  ]
+}
+

Затем в командной строке:

eslint --ext js,vue MyComponent.vue
+

Другим вариантом использования будет eslint-loader, что позволит проверять ваши *.vue файлы автоматически при сохранении на этапе разработки:

npm install -D eslint eslint-loader
+

Убедитесь, что он применяется как предварительный загрузчик:

// webpack.config.js
+module.exports = {
+  // ... другие настройки
+  module: {
+    rules: [
+      {
+        enforce: 'pre',
+        test: /\.(js|vue)$/,
+        loader: 'eslint-loader',
+        exclude: /node_modules/
+      }
+    ]
+  }
+}
+

# stylelint

stylelint поддерживает проверку секций стилей в однофайловых компонентах Vue.

Убедитесь, что ваша конфигурация stylelint корректна.

Затем выполните в командной строке:

stylelint MyComponent.vue
+

Вы также можете использовать плагин stylelint-webpack-plugin:

npm install -D stylelint-webpack-plugin
+

Убедитесь, что добавили плагин в конфигурацию:

// webpack.config.js
+const StyleLintPlugin = require('stylelint-webpack-plugin');
+module.exports = {
+  // ... другие настройки
+  plugins: [
+    new StyleLintPlugin({
+      files: ['**/*.{vue,htm,html,css,sss,less,scss,sass}'],
+    })
+  ]
+}
+
+ + + diff --git a/vue-loader/ru/guide/pre-processors.html b/vue-loader/ru/guide/pre-processors.html new file mode 100644 index 000000000..9919a7660 --- /dev/null +++ b/vue-loader/ru/guide/pre-processors.html @@ -0,0 +1,177 @@ + + + + + + Использование пре-процессоров | Vue Loader + + + + + + + +

# Использование пре-процессоров

В webpack все пре-процессоры должны обрабатываться соответствующими загрузчиками. vue-loader позволяет вам использовать другие загрузчики webpack для обработки секций в однофайловых компонентах Vue. Они будут автоматически вызваны на основе указанного атрибута lang у секции файла.

# Sass

Например, для компиляции нашего тега <style> с помощью Sass/SCSS:

npm install -D sass-loader node-sass
+

В вашей конфигурации webpack:

module.exports = {
+  module: {
+    rules: [
+      // ... другие правила опущены
+
+      // это правило будет применяться к обычным файлам `.scss`
+      // А ТАКЖЕ к секциям `<style lang="scss">` в файлах `.vue`
+      {
+        test: /\.scss$/,
+        use: [
+          'vue-style-loader',
+          'css-loader',
+          'sass-loader'
+        ]
+      }
+    ]
+  },
+  // плагин опущен
+}
+

Теперь, в дополнение к возможности писать import 'style.scss', мы можем использовать SCSS также и в компонентах Vue:

<style lang="scss">
+/* используем SCSS здесь */
+</style>
+

Любое содержимое внутри блока будет обработано webpack, как если бы оно находилось внутри файла *.scss.

# Sass vs SCSS

Обратите внимание, что sass-loader обрабатывает синтаксис scss по умолчанию. Если вам требуется синтаксис sass с отступами, то необходимо передать опцию в загрузчик:

// webpack.config.js -> module.rules
+{
+  test: /\.sass$/,
+  use: [
+    'vue-style-loader',
+    'css-loader',
+    {
+      loader: 'sass-loader',
+      options: {
+        indentedSyntax: true,
+        // sass-loader >= 8
+        sassOptions: {
+          indentedSyntax: true
+        }
+      }
+    }
+  ]
+}
+

# Передача глобальных переменных

sass-loader также поддерживает опцию prependData, которая позволяет вам передавать общие переменные во все обрабатываемые файлы без необходимости везде их явно импортировать:

// webpack.config.js -> module.rules
+{
+  test: /\.scss$/,
+  use: [
+    'vue-style-loader',
+    'css-loader',
+    {
+      loader: 'sass-loader',
+      options: {
+        // вы можете также указать файл, например `variables.scss`
+        // используйте свойство `data` здесь, если версия sass-loader < 8
+        prependData: `$color: red;`
+      }
+    }
+  ]
+}
+

# LESS

npm install -D less less-loader
+
// webpack.config.js -> module.rules
+{
+  test: /\.less$/,
+  use: [
+    'vue-style-loader',
+    'css-loader',
+    'less-loader'
+  ]
+}
+

# Stylus

npm install -D stylus stylus-loader
+
// webpack.config.js -> module.rules
+{
+  test: /\.styl(us)?$/,
+  use: [
+    'vue-style-loader',
+    'css-loader',
+    'stylus-loader'
+  ]
+}
+

# PostCSS

СОВЕТ

Vue Loader v15 больше не применяет трансформацию PostCSS по умолчанию. Вам необходимо использовать PostCSS через postcss-loader.

npm install -D postcss-loader
+
// webpack.config.js -> module.rules
+{
+  test: /\.css$/,
+  use: [
+    'vue-style-loader',
+    {
+      loader: 'css-loader',
+      options: { importLoaders: 1 }
+    },
+    'postcss-loader'
+  ]
+}
+

Конфигурация PostCSS может быть выполнена через postcss.config.js или опции postcss-loader. Подробнее можно прочитать в документации postcss-loader.

postcss-loader может также применяться в комбинации с другими пре-процессорами, указанными выше.

# Babel

npm install -D babel-core babel-loader
+
// webpack.config.js -> module.rules
+{
+  test: /\.js?$/,
+  loader: 'babel-loader'
+}
+

Конфигурация Babel может быть выполнена через .babelrc или опции babel-loader.

# Исключение node_modules

Обычная практика, указывать exclude: /node_modules/ для правил транспиляции JS (например, babel-loader) которые применяются к файлам .js. Из-за изменений версии v15, если вы импортируете однофайловые компоненты SFC внутри node_modules, его секция <script> также будет исключена из транспиляции.

Чтобы обеспечить транспиляцию JS для однофайловых компонентов Vue в node_modules, вам необходимо добавить для них исключение с помощью функции в опции exclude:

{
+  test: /\.js$/,
+  loader: 'babel-loader',
+  exclude: file => (
+    /node_modules/.test(file) &&
+    !/\.vue\.js/.test(file)
+  )
+}
+

# TypeScript

npm install -D typescript ts-loader
+
// webpack.config.js
+module.exports = {
+  resolve: {
+    // Добавляем `.ts` как обрабатываемое расширение.
+    extensions: ['.ts', '.js']
+  },
+  module: {
+    rules: [
+      // ... другие правила опущены
+      {
+        test: /\.ts$/,
+        loader: 'ts-loader',
+        options: { appendTsSuffixTo: [/\.vue$/] }
+      }
+    ]
+  },
+  // ... плагин опущен
+}
+

Конфигурация TypeScipt может быть выполнена через tsconfig.json. Также смотрите документацию для ts-loader.

# Pug

Обработка шаблонов несколько отличается, потому что большинство загрузчиков webpack для шаблонов, такие как pug-loader, возвращают функцию шаблона вместо скомпилированной строки HTML. Вместо использования pug-loader мы должны использовать загрузчик, который вернёт сырую строку HTML, например pug-plain-loader:

npm install -D pug pug-plain-loader
+
// webpack.config.js -> module.rules
+{
+  test: /\.pug$/,
+  loader: 'pug-plain-loader'
+}
+

Теперь вы можете писать:

<template lang="pug">
+div
+  h1 Hello world!
+</template>
+

Если вы также собираетесь импортировать файлы .pug как HTML-строки в JavaScript, вам нужно добавить в цепочку raw-loader после загрузчика пре-процессора. Обратите внимание, что добавление raw-loader сломает использование в компонентах Vue, поэтому потребуется два правила: одно для файлов Vue с использованием resourceQuery, другое (fallback) для импортов из JavaScript:

// webpack.config.js -> module.rules
+{
+  test: /\.pug$/,
+  oneOf: [
+    // это применяется к `<template lang="pug">` в компонентах Vue
+    {
+      resourceQuery: /^\?vue/,
+      use: ['pug-plain-loader']
+    },
+    // это применяется к импортам pug внутри JavaScript
+    {
+      use: ['raw-loader', 'pug-plain-loader']
+    }
+  ]
+}
+
+ + + diff --git a/vue-loader/ru/guide/scoped-css.html b/vue-loader/ru/guide/scoped-css.html new file mode 100644 index 000000000..887e1635d --- /dev/null +++ b/vue-loader/ru/guide/scoped-css.html @@ -0,0 +1,58 @@ + + + + + + Локальный (scoped) CSS | Vue Loader + + + + + + + +

# Локальный (scoped) CSS

Когда у тега <style> есть атрибут scoped, то его CSS будет применяться только к элементам текущего компонента. Это похоже на инкапсуляцию стилей в Shadow DOM. Пользоваться ими можно с некоторыми оговорками, но зато не требуется никаких полифиллов. Это достигается за счёт использования PostCSS для преобразования следующего:

<style scoped>
+.example {
+  color: red;
+}
+</style>
+
+<template>
+  <div class="example">hi</div>
+</template>
+

В что-то подобное:

<style>
+.example[data-v-f3f3eg9] {
+  color: red;
+}
+</style>
+
+<template>
+  <div class="example" data-v-f3f3eg9>hi</div>
+</template>
+

# Использование локальных и глобальных стилей

Вы можете использовать в компоненте локальные и глобальные стилей одновременно:

<style>
+/* глобальные стили */
+</style>
+
+<style scoped>
+/* локальные стили */
+</style>
+

# Корневой элемент дочернего компонента

С помощью scoped, стили родительского компонента не будут влиять на содержимое дочерних компонентов. Тем не менее, корневой элемент дочернего компонента будет зависеть как от локального CSS из родительского элемента, так и от локального CSS дочернего. Это предусмотрено специально, чтобы родительский элемент мог стилизовать корневой элемент дочернего компонента например для целей стилизации.

# Глубокие селекторы

Если вы хотите, чтобы селектор в scoped стилях был "глубоким", т.е. влиял на дочерние компоненты, вы можете использовать комбинатор >>>:

<style scoped>
+.a >>> .b { /* ... */ }
+</style>
+

Указанное выше будет скомпилируется в подобный селектор:

.a[data-v-f3f3eg9] .b { /* ... */ }
+

Некоторые пре-процессоры, такие как Sass, не могут правильно обработать >>>. В таких случаях используйте комбинатор /deep/ или ::v-deep — оба псевдонимы для >>> и работают аналогично.

# Динамически генерируемый контент

DOM-содержимое, создаваемое с помощью v-html не попадает под область действия локальных стилей, но вы всё равно можете его стилизовать с помощью глубоких селекторов.

# О чём следует помнить

  • Локальные стили не устраняют необходимость классов. Из-за того как браузеры рендерят различные CSS-селекторы, p { color: red } может быть в разы медленнее при использовании в локальных стилях (например, когда комбинируется с селектором по атрибуту). Если же вы используете классы или ID, такие как .example { color: red }, тогда вы практически полностью исключаете ухудшение производительности. Вот пример где можете проверить разницу самостоятельно.

  • Будьте внимательны с селекторами потомков в рекурсивных компонентах! Для CSS-правила с селектором .a .b, если элемент, который соответствует .a содержит рекурсивный компонент потомок, тогда все .b в этом компоненте потомке будут также соответствовать правилу.

+ + + diff --git a/vue-loader/ru/guide/testing.html b/vue-loader/ru/guide/testing.html new file mode 100644 index 000000000..1179b4d6f --- /dev/null +++ b/vue-loader/ru/guide/testing.html @@ -0,0 +1,25 @@ + + + + + + Тестирование | Vue Loader + + + + + + + +

# Тестирование

  • Vue CLI предлагает вам готовые решения для модульного и e2e-тестирования.

  • Если вы заинтересованы в ручной настройке модульного тестирования для *.vue файлов, ознакомьтесь с документацией для @vue/test-utils, которая описывает настройку тестов с помощью mocha-webpack или Jest.

+ + + diff --git a/vue-loader/ru/index.html b/vue-loader/ru/index.html new file mode 100644 index 000000000..0deb8e459 --- /dev/null +++ b/vue-loader/ru/index.html @@ -0,0 +1,44 @@ + + + + + + Введение | Vue Loader + + + + + + + +

# Введение

ПРИМЕЧАНИЕ К ВЕРСИИ

Это документация для Vue Loader v15 и выше. Если вы обновляетесь с v14 или более ранних версий, обратитесь к руководству по миграции. Если вы используете старую версию, то документация к ней здесь.

# Что такое Vue Loader?

vue-loader — это загрузчик для webpack, который позволяет вам использовать компоненты Vue в формате, именуемым однофайловыми компонентами:

<template>
+  <div class="example">{{ msg }}</div>
+</template>
+
+<script>
+export default {
+  data () {
+    return {
+      msg: 'Hello world!'
+    }
+  }
+}
+</script>
+
+<style>
+.example {
+  color: red;
+}
+</style>
+

Использование vue-loader предоставляет множество интересных возможностей:

  • Позволяет использовать разнообразные загрузчики webpack для разных секций компонента Vue, например Sass для <style> и Pug для <template>;
  • Позволяет использовать пользовательские секции в файлах .vue, обрабатывая их указанными цепочками загрузчиков;
  • Обращается со статическими ресурсами, указанными в <style> и <template> как с зависимостями модуля и обрабатывает их с помощью загрузчиков webpack;
  • Может эмулировать локальный (scoped) CSS для каждого компонента;
  • Горячая перезагрузка модулей с сохранением состояния на этапе разработки.

В двух словах, сочетание webpack и vue-loader предоставляет вам современный, гибкий и невероятно эффективный подход к написанию клиентских приложений на Vue.js.

+ + + diff --git a/vue-loader/ru/migrating.html b/vue-loader/ru/migrating.html new file mode 100644 index 000000000..9c2d92258 --- /dev/null +++ b/vue-loader/ru/migrating.html @@ -0,0 +1,160 @@ + + + + + + Миграция с версии v14 | Vue Loader + + + + + + + +

# Миграция с версии v14

Будьте внимательны

Мы в процессе обновления Vue CLI 3 beta для использования webpack 4 + Vue Loader v15, поэтому вы можете захотеть подождать, если планируете переход на Vue CLI 3.

# Важные изменения

# Необходимо установить плагин

Vue Loader v15 теперь для правильной работы требуется прилагаемый плагин webpack:

// webpack.config.js
+const VueLoaderPlugin = require('vue-loader/lib/plugin')
+
+module.exports = {
+  // ...
+  plugins: [
+    new VueLoaderPlugin()
+  ]
+}
+

# Определение загрузчиков webpack

Vue Loader v15 теперь использует другую стратегию для определения загрузчиков, которые должны использоваться для языкового блока.

Рассмотрим <style lang="less"> для примера: в версии v14 и ниже, он попытается загрузить блок с помощью less-loader, и неявно добавляет в цепочку загрузчиков css-loader и vue-style-loader после него, используя инлайновые-строки с указанием загрузчиков.

С версии v15, <style lang="less"> будет вести себя так, как если бы это был загруженный файл *.less . Поэтому, чтобы обработать его, вам нужно предоставить явное правило в вашей основной конфигурации webpack:

{
+  module: {
+    rules: [
+      // ... другие правила
+      {
+        test: /\.less$/,
+        use: [
+          'vue-style-loader',
+          'css-loader',
+          'less-loader'
+        ]
+      }
+    ]
+  }
+}
+

Преимущество состоит в том, что это же правило также применяется и к обычным импортам *.less из JavaScript, и вы можете конфигурировать опции для этих загрузчиков так как захотите. В версии v14 и ниже, если вы хотите предоставить пользовательские опции для предполагаемого загрузчика, то вам необходимо дублировать их в собственной опции loaders у Vue Loader. С версии v15 это больше не требуется.

Версия v15 также позволяет использовать не-сериализуемые опции для загрузчиков, что было невозможно в предыдущих версиях.

# Импорт однофайловых компонентов из зависимостей

Обычная практика, указывать exclude: /node_modules/ для правил транспиляции JS (например, babel-loader) которые применяются к файлам .js. Из-за изменения версии v15, если вы импортируете однофайловые компоненты SFC внутри node_modules, его секция <script> также будет исключена из транспиляции.

Чтобы обеспечить транспиляцию JS для однофайловых компонентов Vue в node_modules, вам необходимо делать для них исключение с помощью функции в опции exclude:

{
+  test: /\.js$/,
+  loader: 'babel-loader',
+  exclude: file => (
+    /node_modules/.test(file) &&
+    !/\.vue\.js/.test(file)
+  )
+}
+

# Обработка секций шаблонов

v14 и ниже использует consolidate для компиляции <template lang="xxx">. v15 теперь обрабатывает их с помощью загрузчиков webpack.

Обратите внимание, что некоторые загрузчики шаблонов, такие как pug-loader возвращают функцию шаблона вместо скомпилированной строки HTML. Для того чтобы передать корректное содержимое в компилятор шаблонов Vue, вам необходимо использовать загрузчики, которые вместо этого возвращают простой HTML. Например, для поддержки <template lang="pug">, вы можете использовать pug-plain-loader:

{
+  module: {
+    rules: [
+      {
+        test: /\.pug$/,
+        loader: 'pug-plain-loader'
+      }
+    ]
+  }
+}
+

Если вы также собираетесь импортировать файлы .pug как HTML-строки в JavaScript, вам нужно будет добавить в цепочку raw-loader после загрузчика пре-процессора. Обратите внимание, что добавление raw-loader сломает использование в компонентах Vue, поэтому вам потребуется два правила, одно направленное на файлы Vue с использованием resourceQuery, другое (fallback) нацеленное на импорты JavaScript:

{
+  module: {
+    rules: [
+      {
+        test: /\.pug$/,
+        oneOf: [
+          // это применяется к `<template lang="pug">` в компонентах Vue
+          {
+            resourceQuery: /^\?vue/,
+            use: ['pug-plain-loader']
+          },
+          // это применяется к импортам pug внутри JavaScript
+          {
+            use: ['raw-loader', 'pug-plain-loader']
+          }
+        ]
+      }
+    ]
+  }
+}
+

# Внедрение стилей

Внедрение стилей на стороне клиента теперь внедряет все стили заранее, чтобы обеспечить консистентное поведение между режимом разработки и режимом, когда CSS извлекается в отдельный файл.

Обратите внимание, что порядок внедрения всё ещё не гарантируется, поэтому вам следует избегать написания CSS, который зависит от порядка внедрения.

# PostCSS

Vue Loader больше не применяет трансформацию PostCSS по умолчанию. Для использования PostCSS сконфигурирйте postcss-loader таким образом, как и для обычных CSS файлов.

# CSS модули

CSS модули теперь должны явно настраиваться через опцию css-loader. Атрибут module на тегах <style> по-прежнему необходим для локального внедрения в компонент.

Хорошая новость в том, что теперь вы можете настраивать localIdentName в одном месте:

{
+  module: {
+    rules: [
+      {
+        test: /\.css$/,
+        use: [
+          {
+            loader: 'vue-style-loader'
+          },
+          {
+            loader: 'css-loader',
+            options: {
+              modules: true,
+              localIdentName: '[local]_[hash:base64:8]'
+            }
+          }
+        ]
+      }
+    ]
+  }
+}
+

Если вы хотите использовать CSS модули только в некоторых компонентах Vue, вы можете использовать правило oneOf и проверять наличие строки module внутри resourceQuery:

{
+  test: /\.css$/,
+  oneOf: [
+    // это соответствует `<style module>`
+    {
+      resourceQuery: /module/,
+      use: [
+        'vue-style-loader',
+        {
+          loader: 'css-loader',
+          options: {
+            modules: true,
+            localIdentName: '[local]_[hash:base64:5]'
+          }
+        }
+      ]
+    },
+    // это соответствует простому `<style>` или `<style scoped>`
+    {
+      use: [
+        'vue-style-loader',
+        'css-loader'
+      ]
+    }
+  ]
+}
+

# Извлечение CSS в отдельный файл

Работает аналогично тому, как вы бы настроили его для обычного CSS. Пример использования с помощью mini-css-extract-plugin:

{
+  module: {
+    rules: [
+      {
+        test: /\.vue$/,
+        use: 'vue-loader'
+      },
+      {
+        test: /\.css$/,
+        // или `ExtractTextWebpackPlugin.extract(...)`
+        use: [
+          MiniCssExtractPlugin.loader,
+          'css-loader'
+        ]
+      }
+    ]
+  },
+  plugins: [
+    new MiniCssExtractPlugin({
+      filename: 'output.css'
+    })
+  ]
+}
+

# SSR externals

В SSR, мы обычно используем webpack-node-externals для исключения npm-зависимостей из серверной сборки. Если вам необходимо импортировать CSS из npm-зависимости, то предыдущим решением было указать белый список, например так:

// конфигурация webpack
+externals: nodeExternals({
+  whitelist: /\.css$/
+})
+

С версии v15, импорты для <style src="dep/foo.css"> получают строку resourceQuery, добавленную в конце запроса, поэтому вам потребуется обновить белый список так:

externals: nodeExternals({
+  whitelist: [/\.css$/, /\?vue&type=style/]
+})
+

# Устаревшие опции

Следующие опции объявлены устаревшими и должны настраиваться с использованием обычных правил модулей webpack:

  • loader
  • preLoaders
  • postLoaders
  • postcss
  • cssSourceMap
  • buble
  • extractCSS
  • template

Следующие опции объявлены устаревшими и должны настраиваться с помощью новой опции compilerOptions:

  • preserveWhitespace (используйте compilerOptions.preserveWhitespace)
  • compilerModules (используйте compilerOptions.modules)
  • compilerDirectives (используйте compilerOptions.directives)

Следующие опции были переименованы:

  • transformToRequire (переименована в transformAssetUrls)

СОВЕТ

Полный список новых опций можно посмотреть на странице настроек.

+ + + diff --git a/vue-loader/ru/options.html b/vue-loader/ru/options.html new file mode 100644 index 000000000..ad835d15e --- /dev/null +++ b/vue-loader/ru/options.html @@ -0,0 +1,29 @@ + + + + + + Настройки | Vue Loader + + + + + + + +

# Настройки

# transformAssetUrls

  • Тип: { [tag: string]: string | Array<string> }

  • По умолчанию:

    {
    +  video: ['src', 'poster'],
    +  source: 'src',
    +  img: 'src',
    +  image: ['xlink:href', 'href'],
    +  use: ['xlink:href', 'href']
    +}
    +

    Во время компиляции шаблона, компилятор может преобразовывать определённые атрибуты, такие как URL-адреса в src, в вызовы require, чтобы указанный ресурс обрабатывался с помощью webpack. Например, <img src="./foo.png"> будет пытаться найти файл ./foo.png в вашей файловой системе и добавит его как зависимость сборки.

# compiler

  • Тип: VueTemplateCompiler

  • По умолчанию: require('vue-template-compiler')

    Переопределение компилятора по умолчанию, используемого для компиляции секций <template> в однофайловых компонентах.

# compilerOptions

  • Тип: Object

  • По умолчанию: {}

    Настройки для компилятора шаблонов. При использовании по умолчанию vue-template-compiler вы можете использовать эту опцию чтобы добавить пользовательские директивы компилятора, модули, или с помощью { preserveWhitespace: false } игнорировать пробелы между тегами.

    Подробнее в перечне опций vue-template-compiler.

# transpileOptions

  • Тип: Object

  • По умолчанию: {}

    Опции транспиляции ES2015+ в ES5 для генерируемого кода render-функций. Транспилятор — форк Buble, поэтому полный список опций вы можете посмотреть здесь.

    Компиляция render-функций шаблонов поддерживает специальную трансформацию stripWith (включена по умолчанию), которая удаляет использование with в сгенерированных render-функциях, чтобы сделать их совместимыми со strict-режимом.

# optimizeSSR

  • Тип: boolean

  • По умолчанию: true когда конфигурация webpack имеет свойство target: 'node' и версия vue-template-compiler 2.4.0 или выше.

    Включает оптимизацию для серверного рендеринга в Vue 2.4, которая компилирует в простые строки часть деревьев vdom, возвращаемых render-функциями, что улучшает производительность серверного рендеринга. В некоторых случаях вам может потребоваться явно отключить оптимизацию, поскольку результирующие render-функции могут быть использованы только для серверного рендеринга и не могут использоваться для рендеринга на стороне клиента или тестирования.

# hotReload

  • Тип: boolean

  • По умолчанию: true в режиме разработки, false в режиме production или при установленной опции target: 'node' в конфигурации webpack.

  • Разрешённые значения: false (true не заставит работать горячую перезагрузку ни в режиме production, ни когда target: 'node')

    Возможность webpack по горячей перезагрузке модулей позволяет применять изменения в браузере без необходимости обновления страницы. +Используйте эту опцию (со значением false) чтобы отключить горячую перезагрузку в режиме разработки.

# productionMode

  • Тип: boolean
  • По умолчанию: process.env.NODE_ENV === 'production'

Позволяет принудительно включить режим production, который исключит из сборки код, необходимый только на этапе разработки (например, горячую перезагрузку модулей).

# shadowMode

  • Тип: boolean
  • По умолчанию: false

Компилирует компонент для использования внутри Shadow DOM. В этом режиме стили компонента внедряются в this.$root.$options.shadowRoot вместо head-тега документа.

# cacheDirectory / cacheIdentifier

  • Тип: string
  • По умолчанию: undefined

Когда указаны оба параметра, включает кэширование в файловой системе скомпилированных шаблонов (требуется, чтобы cache-loader был установлен в том же проекте).

СОВЕТ

Взаимодействие между vue-loader и cache-loader использует инлайновый синтаксис импорта загрузчиков внутри, где символ ! будет рассматриваться как разделитель между различными загрузчиками. Поэтому убедитесь, что cacheDirectory не содержит символов !.

# prettify

  • Тип: boolean
  • По умолчанию: true

В режиме разработки по умолчанию используется prettier для форматирования скомпилированной render-функции для удобства отладки. Однако, если вы столкнётесь с какой-либо непонятной ошибкой самого prettier, такой как экспоненциальное время компиляции для глубоко вложенных функций, можно отключить эту опцию.

# exposeFilename

  • Тип: boolean
  • По умолчанию: false

В не-production окружениях vue-loader внедряет свойство __file в компоненты для улучшения отладки. Если свойство name отсутствует в компоненте, Vue будет использовать значение из __file для отображения предупреждений в консоли.

Это свойство удаляется из сборки для production по умолчанию. Но вы можете сохранить его, если вы разрабатываете библиотеку компонентов и не хотите указывать name в каждом компоненте. В таком случае вы можете включить эту опцию.

+ + + diff --git a/vue-loader/ru/spec.html b/vue-loader/ru/spec.html new file mode 100644 index 000000000..cdca99140 --- /dev/null +++ b/vue-loader/ru/spec.html @@ -0,0 +1,54 @@ + + + + + + Однофайловые компоненты Vue | Vue Loader + + + + + + + +

# Однофайловые компоненты Vue

# Введение

Файл *.vue это собственный формат Vue, использующий HTML-подобный синтаксис для описания компонента. Каждый *.vue файл состоит из трёх главных секций: <template>, <script> и <style>, а также опциональных пользовательских блоков:

<template>
+  <div class="example">{{ msg }}</div>
+</template>
+
+<script>
+export default {
+  data () {
+    return {
+      msg: 'Hello world!'
+    }
+  }
+}
+</script>
+
+<style>
+.example {
+  color: red;
+}
+</style>
+
+<custom1>
+  Это может быть, например, документация для компонента
+</custom1>
+

vue-loader парсит файл, извлекает каждую из секций, обрабатывает их при необходимости другими загрузчиками webpack, и в итоге собирает всё обратно в ES-модуль где экспорт по умолчанию будет объектом настроек компонента Vue.js.

vue-loader предоставляет возможность использовать нестандартные языки, например пре-процессоры CSS и языки шаблонов компилируемые в HTML, указывая атрибут lang для секции файла. Например, вы можете использовать Sass для стилей вашего компонента:

<style lang="sass">
+  /* используем Sass! */
+</style>
+

Подробнее на странице использования пре-процессоров.

# Секции файла

# Шаблон (template)

  • Каждый *.vue файл может содержать максимум один блок <template>.

  • Содержимое извлекается, передаётся в vue-template-compiler, где предварительно будет скомпилировано в JavaScript render-функции, и наконец внедряется в описываемый компонент в секции <script>.

# Логика (script)

  • Каждый *.vue файл может содержать максимум один блок <script>.

  • Секция исполняется как ES-модуль.

  • Экспорт по умолчанию должен быть объектом опций компонента Vue.js. Экспортирование расширенного конструктора, созданного с помощью Vue.extend() также поддерживается, но обычный объект предпочтителен.

  • Любые правила webpack, которые совпадут с форматом .js файлов (или расширения, указанного в атрибуте lang) также будут применены к содержимому блока <script>.

# Стили (style)

  • По умолчанию считается: /\.css$/.

  • Может быть несколько тегов <style> в одном *.vue файле.

  • Тег <style> может иметь атрибуты scoped или module (подробнее — Локальный (scoped) CSS и CSS модули) для возможности инкапсулировать стили в текущий компонент. Несколько тегов <style> с разными режимами инкапсуляции могут быть использованы в одном компоненте.

  • Любые правила webpack, которые совпадут с форматом .css файлов (или расширения, указанного в атрибуте lang) также будут применены к содержимому блока <style>.

# Пользовательские блоки

Дополнительные пользовательские блоки могут быть добавлены в *.vue файл для любых потребностей проекта, например блок <docs>. vue-loader будет использовать имя тега для определения какими загрузчиками webpack требуется обрабатывать содержимое этой секции. Загрузчики webpack должны быть указаны в секции loaders настроек vue-loader.

Подробнее в разделе пользовательских блоков.

# Импорты из других файлов

Если вы предпочитаете разделять *.vue компоненты на несколько файлов, вы можете использовать атрибут src для импорта содержимого другого файла в секцию, например:

<template src="./template.html"></template>
+<style src="./style.css"></style>
+<script src="./script.js"></script>
+

Обратите внимание, что импорты через src следуют тем же правилам webpack по разрешению путей к модулям, что означает:

  • Относительные пути должны начинаться с ./
  • Вы можете импортировать ресурсы из npm-зависимостей:
<!-- импорт файла из установленного npm-пакета "todomvc-app-css" -->
+<style src="todomvc-app-css/index.css">
+

src импорты также работают с пользовательскими блоками, например:

<unit-test src="./unit-test.js">
+</unit-test>
+

# Подсветка синтаксиса / поддержка IDE

На данный момент есть поддержка подсветки синтаксиса для следующих IDE/редакторов:

Будем рады видеть разработки и для других редакторов и IDE! Если вы не используете никаких пре-процессоров в компонентах Vue, вы также можете использовать синтаксис HTML в вашем редакторе для *.vue файлов.

# Комментарии

Внутри каждой секции вы можете использовать синтаксис комментариев, который соответствует используемому языку (HTML, CSS, JavaScript, Pug, и т.д.). Для комментариев на уровне секций, используйте синтаксис комментариев HTML: <!-- ваш комментарий -->

+ + + diff --git a/vue-loader/service-worker.js b/vue-loader/service-worker.js new file mode 100644 index 000000000..bab715b76 --- /dev/null +++ b/vue-loader/service-worker.js @@ -0,0 +1,428 @@ +/** + * Welcome to your Workbox-powered service worker! + * + * You'll need to register this file in your web app and you should + * disable HTTP caching for this file too. + * See https://goo.gl/nhQhGp + * + * The rest of the code is auto-generated. Please don't update this file + * directly; instead, make changes to your Workbox build configuration + * and re-run your build process. + * See https://goo.gl/2aRDsh + */ + +importScripts("https://storage.googleapis.com/workbox-cdn/releases/3.6.3/workbox-sw.js"); + +/** + * The workboxSW.precacheAndRoute() method efficiently caches and responds to + * requests for URLs in the manifest. + * See https://goo.gl/S9QRab + */ +self.__precacheManifest = [ + { + "url": "404.html", + "revision": "a3c961f3504703947818aa0b4fb0d4af" + }, + { + "url": "assets/css/0.styles.a8bea730.css", + "revision": "d0b537ef16d0f6513425ac194ac0d288" + }, + { + "url": "assets/img/search.83621669.svg", + "revision": "83621669651b9a3d4bf64d1a670ad856" + }, + { + "url": "assets/js/10.a114b627.js", + "revision": "e2c44df2c2c8a2b79a6b6e3d6a7ef9f3" + }, + { + "url": "assets/js/11.6fd19879.js", + "revision": "7ee0747092a2ba2b39916f1bf0e3dc1a" + }, + { + "url": "assets/js/12.9ff015c3.js", + "revision": "5d95a86190d937caf954294e29d122cb" + }, + { + "url": "assets/js/13.26a4de36.js", + "revision": "756c162ee528e87456b0113c251b99ee" + }, + { + "url": "assets/js/14.95dab746.js", + "revision": "c93133009ca4c10032629be6f83b399f" + }, + { + "url": "assets/js/15.9691e94d.js", + "revision": "a0b457487c66e9367becbd40a4bfcac7" + }, + { + "url": "assets/js/16.101542f7.js", + "revision": "29b53df572c535b5018025be33282a17" + }, + { + "url": "assets/js/17.79058574.js", + "revision": "0e509258ad4c0f971471128f82707c65" + }, + { + "url": "assets/js/18.0c482506.js", + "revision": "628ed144f59c8d0059e7d347835357a7" + }, + { + "url": "assets/js/19.ac07cf62.js", + "revision": "9add65f9db3b992a5744ad4c05866ade" + }, + { + "url": "assets/js/20.92c6a40f.js", + "revision": "732cdd7654b73f5085dc4dc994d30e0d" + }, + { + "url": "assets/js/21.77548eb9.js", + "revision": "cefe4647147e71fc29dae06e4931e1ea" + }, + { + "url": "assets/js/22.b6bf8595.js", + "revision": "98fe33aef6b541961d8220d7525afbc6" + }, + { + "url": "assets/js/23.5fc70ac9.js", + "revision": "cb4ea277cb4e1040ef0eaf0af072fd94" + }, + { + "url": "assets/js/24.24ae9220.js", + "revision": "904c8935edde0a3e59dd43c8b997c5cd" + }, + { + "url": "assets/js/25.6063ea01.js", + "revision": "1ca7b9f8f04177a49889d2da9f124181" + }, + { + "url": "assets/js/26.e5bb7520.js", + "revision": "28d045912d3164384bd32a61e59a92d7" + }, + { + "url": "assets/js/27.b11f490e.js", + "revision": "dba628bb6d54424b2daa7c0d6335ff59" + }, + { + "url": "assets/js/28.5e90e383.js", + "revision": "cbbbbcbfd751e2a338fb70ea998e6cce" + }, + { + "url": "assets/js/29.2a4dae4f.js", + "revision": "04e670be337306d6ddd4c79d6b424274" + }, + { + "url": "assets/js/3.e07a48a0.js", + "revision": "6c4cec4747c2d212bee82feb9b1aad96" + }, + { + "url": "assets/js/30.28b9256b.js", + "revision": "0dfe23a14eabb4dcb47f2a0a32ad944c" + }, + { + "url": "assets/js/31.4370a0a5.js", + "revision": "9f10fb666b101e3ba7d95e53fedb3904" + }, + { + "url": "assets/js/32.6119b413.js", + "revision": "b47ce44ff62b9ba3e59485a528fc46c6" + }, + { + "url": "assets/js/33.3b8e35a2.js", + "revision": "dcde8118e334d19863b4a529ddbd5192" + }, + { + "url": "assets/js/34.8771fa00.js", + "revision": "3ba575bed1d9502190c58a627e0af142" + }, + { + "url": "assets/js/35.012ac30a.js", + "revision": "4cbcca115ea481a73965a7e404770e47" + }, + { + "url": "assets/js/36.fae7bb1f.js", + "revision": "b9ad1007e559c913120881b5425f8300" + }, + { + "url": "assets/js/37.9aaa69b9.js", + "revision": "c7cde058c5ad66647fceade916954b6d" + }, + { + "url": "assets/js/38.38a51b35.js", + "revision": "afab84c0b33e07b76c0111621cdf9349" + }, + { + "url": "assets/js/39.8ca2086e.js", + "revision": "21f501a761032053ff0e37dbe3cece24" + }, + { + "url": "assets/js/4.542c9ac2.js", + "revision": "b3fa218eaf811c46b9bcf3a48dd59453" + }, + { + "url": "assets/js/40.77aa05e5.js", + "revision": "9ca9450cdee24a54fea487e2b2127709" + }, + { + "url": "assets/js/41.ec414567.js", + "revision": "62223bc01e39c309596a653ad23b1aa8" + }, + { + "url": "assets/js/42.26494577.js", + "revision": "0968403768c19c8ff119595fb99c68b7" + }, + { + "url": "assets/js/43.9c9043ab.js", + "revision": "50a2cf25359b02cecdb235f2cb498941" + }, + { + "url": "assets/js/44.ab29c922.js", + "revision": "e3f1da6ddd30d4f62da0127a81fde66c" + }, + { + "url": "assets/js/45.4193dd8c.js", + "revision": "e68fb6afa111e7d8e79e888f0469301b" + }, + { + "url": "assets/js/46.372e44b4.js", + "revision": "ead4fbbee3ad8bc49f36efb2c4539cf3" + }, + { + "url": "assets/js/47.bbf8de2f.js", + "revision": "64ba17be6cca7c8dae75810727bb76a2" + }, + { + "url": "assets/js/48.e6a9e8c4.js", + "revision": "d506e81e1b4509f20ef37b646b1e36fc" + }, + { + "url": "assets/js/49.5b519d29.js", + "revision": "de9b072742c2c0782f51d0af332bb4cc" + }, + { + "url": "assets/js/5.6b22a1a4.js", + "revision": "4c5d6e36fade28ba21583ba6c1cb6aab" + }, + { + "url": "assets/js/6.1019449d.js", + "revision": "0a06cfc64265c82ba082ce6222d7998b" + }, + { + "url": "assets/js/7.23820790.js", + "revision": "72454d50391d7cbaca0c50992674df9f" + }, + { + "url": "assets/js/8.70e971cc.js", + "revision": "b229f3cb4e1432939a8dc14991f3c053" + }, + { + "url": "assets/js/9.c287a132.js", + "revision": "9446b93aa17449a4ac1b9e5d28d44e9e" + }, + { + "url": "assets/js/app.f08d727e.js", + "revision": "4171576d661cae2148734735fc4040de" + }, + { + "url": "assets/js/vendors~docsearch.ade5e3f2.js", + "revision": "32162c001c1ba4ee13067ecea07d4480" + }, + { + "url": "guide/asset-url.html", + "revision": "b9e9d75a36c7899dd2e48b69d116699b" + }, + { + "url": "guide/css-modules.html", + "revision": "7655ac22d83ff20e8ba9803850767fa3" + }, + { + "url": "guide/custom-blocks.html", + "revision": "ce3291102e711b7c0a3329e955319e57" + }, + { + "url": "guide/extract-css.html", + "revision": "fcbdf9194f728bc2c245ad3523cbcd72" + }, + { + "url": "guide/functional.html", + "revision": "02cf2619a90dd473f022b8fdb3a4999e" + }, + { + "url": "guide/hot-reload.html", + "revision": "f9131fe269e03f4377f4a949c553cdbb" + }, + { + "url": "guide/index.html", + "revision": "7db67e46e1ddb6ab420432e99a3339d1" + }, + { + "url": "guide/linting.html", + "revision": "717f10ad1756458b933e4ff97cfef007" + }, + { + "url": "guide/pre-processors.html", + "revision": "66cf0545984e671b7c44c8688816dbcf" + }, + { + "url": "guide/scoped-css.html", + "revision": "39b66e84c2b367c9680c35e91008172d" + }, + { + "url": "guide/testing.html", + "revision": "7fab396073fc5acb7ec0d48b672e3ad0" + }, + { + "url": "hot-reload.gif", + "revision": "d2aa27b9ebb38b8550207af7284b5e27" + }, + { + "url": "index.html", + "revision": "9f0737c1fa628a6ea970e9ea8c83a683" + }, + { + "url": "migrating.html", + "revision": "b0e514f15a27be460cafacbe327515bf" + }, + { + "url": "options.html", + "revision": "66eb81652c974a9342f09e74fba31750" + }, + { + "url": "ru/guide/asset-url.html", + "revision": "f434d1d25195d9ac71b7af4b4a538e3f" + }, + { + "url": "ru/guide/css-modules.html", + "revision": "0cc5d5ef7b9f504f1cc9d327ef2d504e" + }, + { + "url": "ru/guide/custom-blocks.html", + "revision": "b135444360a77906a6cfcc0c2918baf0" + }, + { + "url": "ru/guide/extract-css.html", + "revision": "91252d76d344daf62674c98658a7a8eb" + }, + { + "url": "ru/guide/functional.html", + "revision": "04eff16367a625f9139300bfa5528f5c" + }, + { + "url": "ru/guide/hot-reload.html", + "revision": "138cd82ca14e7ca89b30002d5d5b817d" + }, + { + "url": "ru/guide/index.html", + "revision": "e09e2c95cd08b881ecf3d766b8d924e8" + }, + { + "url": "ru/guide/linting.html", + "revision": "5020ba29a342fe4f43c548c7f2479c24" + }, + { + "url": "ru/guide/pre-processors.html", + "revision": "14c01ca817d7b8cfdd54ad908e6e7bfb" + }, + { + "url": "ru/guide/scoped-css.html", + "revision": "1a71f326326c735d9f41cb868d366c87" + }, + { + "url": "ru/guide/testing.html", + "revision": "406b085b020b555375cbc20a3b0d0924" + }, + { + "url": "ru/index.html", + "revision": "1f6fdf83f32d5dcc99f30e456e46d673" + }, + { + "url": "ru/migrating.html", + "revision": "697305e92951ec5c3b808c0f975f968a" + }, + { + "url": "ru/options.html", + "revision": "a3e5d42faafe1c60985a43d8a2fb2d17" + }, + { + "url": "ru/spec.html", + "revision": "5680308dd20e422814623e90d296d72b" + }, + { + "url": "spec.html", + "revision": "a219437e7df811b49d219721deca9b69" + }, + { + "url": "zh/guide/asset-url.html", + "revision": "b2433c03c75a4bd4f020ebe90980c95a" + }, + { + "url": "zh/guide/css-modules.html", + "revision": "e293481352fa7df02c491d4addfa9555" + }, + { + "url": "zh/guide/custom-blocks.html", + "revision": "0b5adbfd512d0ce3e5968e82131507ec" + }, + { + "url": "zh/guide/extract-css.html", + "revision": "206d9d7c9f08d0ce36b9b2e9ae296f6e" + }, + { + "url": "zh/guide/functional.html", + "revision": "776b694f78e1b79f3439cc458e3ced7a" + }, + { + "url": "zh/guide/hot-reload.html", + "revision": "9e84b41049ccb8ea9ff6a9df4d19027a" + }, + { + "url": "zh/guide/index.html", + "revision": "2bfc3be4dd02d7bbde4521335803d1d8" + }, + { + "url": "zh/guide/linting.html", + "revision": "e145cc4d192572923ae669ec23428949" + }, + { + "url": "zh/guide/pre-processors.html", + "revision": "d1fe3e3c0310981db794371c2c8421b5" + }, + { + "url": "zh/guide/scoped-css.html", + "revision": "b7e9e48c3e0822da3119e9498d84dfe6" + }, + { + "url": "zh/guide/testing.html", + "revision": "c5b30d9f7cf1e57b4d9475f0cf9abac5" + }, + { + "url": "zh/index.html", + "revision": "0b61bcb472e6a6349d2a43479f390556" + }, + { + "url": "zh/migrating.html", + "revision": "7b2f3988c665419454bcfa5afb926ee6" + }, + { + "url": "zh/options.html", + "revision": "af3a7ba787108a0435e82c08fcd424e0" + }, + { + "url": "zh/spec.html", + "revision": "6ea5c7743ae13592193c61e389920ff4" + } +].concat(self.__precacheManifest || []); +workbox.precaching.suppressWarnings(); +workbox.precaching.precacheAndRoute(self.__precacheManifest, {}); +addEventListener('message', event => { + const replyPort = event.ports[0] + const message = event.data + if (replyPort && message && message.type === 'skip-waiting') { + event.waitUntil( + self.skipWaiting().then( + () => replyPort.postMessage({ error: null }), + error => replyPort.postMessage({ error }) + ) + ) + } +}) diff --git a/vue-loader/spec.html b/vue-loader/spec.html new file mode 100644 index 000000000..08cad4ad8 --- /dev/null +++ b/vue-loader/spec.html @@ -0,0 +1,54 @@ + + + + + + SFC Spec | Vue Loader 中文文档 + + + + + + + +

# Vue Single-File Component (SFC) Spec

# Intro

A *.vue file is a custom file format that uses HTML-like syntax to describe a Vue component. Each *.vue file consists of three types of top-level language blocks: <template>, <script>, and <style>, and optionally additional custom blocks:

<template>
+  <div class="example">{{ msg }}</div>
+</template>
+
+<script>
+export default {
+  data () {
+    return {
+      msg: 'Hello world!'
+    }
+  }
+}
+</script>
+
+<style>
+.example {
+  color: red;
+}
+</style>
+
+<custom1>
+  This could be e.g. documentation for the component.
+</custom1>
+

vue-loader will parse the file, extract each language block, pipe them through other loaders if necessary, and finally assemble them back into an ES Module whose default export is a Vue.js component options object.

vue-loader supports using non-default languages, such as CSS pre-processors and compile-to-HTML template languages, by specifying the lang attribute for a language block. For example, you can use Sass for the style of your component like this:

<style lang="sass">
+  /* write Sass! */
+</style>
+

More details can be found in Using Pre-Processors.

# Language Blocks

# Template

  • Each *.vue file can contain at most one <template> block at a time.

  • Contents will be extracted and passed on to vue-template-compiler and pre-compiled into JavaScript render functions, and finally injected into the exported component in the <script> section.

# Script

  • Each *.vue file can contain at most one <script> block at a time.

  • The script is executed as an ES Module.

  • The default export should be a Vue.js component options object. Exporting an extended constructor created by Vue.extend() is also supported, but a plain object is preferred.

  • Any webpack rules that match against .js files (or the extension specified by the lang attribute) will be applied to contents in the <script> block as well.

# Style

  • Default match: /\.css$/.

  • A single *.vue file can contain multiple <style> tags.

  • A <style> tag can have scoped or module attributes (see Scoped CSS and CSS Modules) to help encapsulate the styles to the current component. Multiple <style> tags with different encapsulation modes can be mixed in the same component.

  • Any webpack rules that match against .css files (or the extension specified by the lang attribute) will be applied to contents in the <style> blocks as well.

# Custom Blocks

Additional custom blocks can be included in a *.vue file for any project specific needs, for example a <docs> block. vue-loader will use the tag name to look up which webpack loaders should be applied to the contents of the section. The webpack loaders should be specified in the loaders section of vue-loader options.

For more details, see Custom Blocks.

# Src Imports

If you prefer splitting up your *.vue components into multiple files, you can use the src attribute to import an external file for a language block:

<template src="./template.html"></template>
+<style src="./style.css"></style>
+<script src="./script.js"></script>
+

Beware that src imports follow the same path resolution rules to webpack module requests, which means:

  • Relative paths need to start with ./
  • You can import resources from npm dependencies:
<!-- import a file from the installed "todomvc-app-css" npm package -->
+<style src="todomvc-app-css/index.css">
+

src imports also work with custom blocks, e.g.:

<unit-test src="./unit-test.js">
+</unit-test>
+

# Syntax Highlighting / IDE Support

Currently there is syntax highlighting support for the following IDE/editors:

Contributions for other editors/IDEs are highly appreciated! If you are not using any pre-processors in Vue components, you can also get decent syntax highlighting by treating *.vue files as HTML in your editor.

# Comments

Inside each block you shall use the comment syntax of the language being used (HTML, CSS, JavaScript, Jade, etc). For top-level comments, use HTML comment syntax: <!-- comment contents here -->

+ + + diff --git a/vue-loader/zh/guide/asset-url.html b/vue-loader/zh/guide/asset-url.html new file mode 100644 index 000000000..f59ceebef --- /dev/null +++ b/vue-loader/zh/guide/asset-url.html @@ -0,0 +1,43 @@ + + + + + + 处理资源路径 | Vue Loader 中文文档 + + + + + + + +

# 处理资源路径

当 Vue Loader 编译单文件组件中的 <template> 块时,它也会将所有遇到的资源 URL 转换为 webpack 模块请求

例如,下面的模板代码片段:

<img src="../image.png">
+

将会被编译成为:

createElement('img', {
+  attrs: {
+    src: require('../image.png') // 现在这是一个模块的请求了
+  }
+})
+

默认下列标签/特性的组合会被转换,且这些组合时可以使用 transformAssetUrls 选项进行配置的。

{
+  video: ['src', 'poster'],
+  source: 'src',
+  img: 'src',
+  image: ['xlink:href', 'href'],
+  use: ['xlink:href', 'href']
+}
+

此外,如果你配置了为 <style> 块使用 css-loader,则你的 CSS 中的资源 URL 也会被同等处理。

# 转换规则

资源 URL 转换会遵循如下规则:

  • 如果路径是绝对路径 (例如 /images/foo.png),会原样保留。

  • 如果路径以 . 开头,将会被看作相对的模块依赖,并按照你的本地文件系统上的目录结构进行解析。

  • 如果路径以 ~ 开头,其后的部分将会被看作模块依赖。这意味着你可以用该特性来引用一个 Node 依赖中的资源:

    <img src="~some-npm-package/foo.png">
    +
  • 如果路径以 @ 开头,也会被看作模块依赖。如果你的 webpack 配置中给 @ 配置了 alias,这就很有用了。所有 vue-cli 创建的项目都默认配置了将 @ 指向 /src

# 相关的 Loader

因为像 .png 这样的文件不是一个 JavaScript 模块,你需要配置 webpack 使用 file-loader 或者 url-loader 去合理地处理它们。通过 Vue CLI 创建的项目已经把这些预配置好了。

# 为什么

转换资源 URL 的好处是:

  1. file-loader 可以指定要复制和放置资源文件的位置,以及如何使用版本哈希命名以获得更好的缓存。此外,这意味着 你可以就近管理图片文件,可以使用相对路径而不用担心部署时 URL 的问题。使用正确的配置,webpack 将会在打包输出中自动重写文件路径为正确的 URL。

  2. url-loader 允许你有条件地将文件转换为内联的 base-64 URL (当文件小于给定的阈值),这会减少小文件的 HTTP 请求数。如果文件大于该阈值,会自动的交给 file-loader 处理。

+ + + diff --git a/vue-loader/zh/guide/css-modules.html b/vue-loader/zh/guide/css-modules.html new file mode 100644 index 000000000..a74c8dbed --- /dev/null +++ b/vue-loader/zh/guide/css-modules.html @@ -0,0 +1,130 @@ + + + + + + CSS Modules | Vue Loader 中文文档 + + + + + + + +

# CSS Modules

CSS Modules 是一个流行的,用于模块化和组合 CSS 的系统。vue-loader 提供了与 CSS Modules 的一流集成,可以作为模拟 scoped CSS 的替代方案。

# 用法

首先,CSS Modules 必须通过向 css-loader 传入 modules: true 来开启:

// webpack.config.js
+{
+  module: {
+    rules: [
+      // ... 其它规则省略
+      {
+        test: /\.css$/,
+        use: [
+          'vue-style-loader',
+          {
+            loader: 'css-loader',
+            options: {
+              // 开启 CSS Modules
+              modules: true,
+              // 自定义生成的类名
+              localIdentName: '[local]_[hash:base64:8]'
+            }
+          }
+        ]
+      }
+    ]
+  }
+}
+

然后在你的 <style> 上添加 module 特性:

<style module>
+.red {
+  color: red;
+}
+.bold {
+  font-weight: bold;
+}
+</style>
+

这个 module 特性指引 Vue Loader 作为名为 $style 的计算属性,向组件注入 CSS Modules 局部对象。然后你就可以在模板中通过一个动态类绑定来使用它了:

<template>
+  <p :class="$style.red">
+    This should be red
+  </p>
+</template>
+

因为这是一个计算属性,所以它也支持 :class 的对象/数组语法:

<template>
+  <div>
+    <p :class="{ [$style.red]: isRed }">
+      Am I red?
+    </p>
+    <p :class="[$style.red, $style.bold]">
+      Red and bold
+    </p>
+  </div>
+</template>
+

你也可以通过 JavaScript 访问到它:

<script>
+export default {
+  created () {
+    console.log(this.$style.red)
+    // -> "red_1VyoJ-uZ"
+    // 一个基于文件名和类名生成的标识符
+  }
+}
+</script>
+

你可以查阅 CSS Modules 规范了解更多细节,诸如 global exceptionscomposition 等。

# 可选用法

如果你只想在某些 Vue 组件中使用 CSS Modules,你可以使用 oneOf 规则并在 resourceQuery 字符串中检查 module 字符串:

// webpack.config.js -> module.rules
+{
+  test: /\.css$/,
+  oneOf: [
+    // 这里匹配 `<style module>`
+    {
+      resourceQuery: /module/,
+      use: [
+        'vue-style-loader',
+        {
+          loader: 'css-loader',
+          options: {
+            modules: true,
+            localIdentName: '[local]_[hash:base64:5]'
+          }
+        }
+      ]
+    },
+    // 这里匹配普通的 `<style>` 或 `<style scoped>`
+    {
+      use: [
+        'vue-style-loader',
+        'css-loader'
+      ]
+    }
+  ]
+}
+

# 和预处理器配合使用

CSS Modules 可以与其它预处理器一起使用:

// webpack.config.js -> module.rules
+{
+  test: /\.scss$/,
+  use: [
+    'vue-style-loader',
+    {
+      loader: 'css-loader',
+      options: { modules: true }
+    },
+    'sass-loader'
+  ]
+}
+

# 自定义的注入名称

.vue 中你可以定义不止一个 <style>,为了避免被覆盖,你可以通过设置 module 属性来为它们定义注入后计算属性的名称。

<style module="a">
+  /* 注入标识符 a */
+</style>
+
+<style module="b">
+  /* 注入标识符 b */
+</style>
+
+ + + diff --git a/vue-loader/zh/guide/custom-blocks.html b/vue-loader/zh/guide/custom-blocks.html new file mode 100644 index 000000000..315367677 --- /dev/null +++ b/vue-loader/zh/guide/custom-blocks.html @@ -0,0 +1,89 @@ + + + + + + 自定义块 | Vue Loader 中文文档 + + + + + + + +

# 自定义块

.vue 文件中,你可以自定义语言块。应用于一个自定义块的 loader 是基于这个块的 lang 特性、块的标签名以及你的 webpack 配置进行匹配的。

如果指定了一个 lang 特性,则这个自定义块将会作为一个带有该 lang 扩展名的文件进行匹配。

你也可以使用 resourceQuery 来为一个没有 lang 的自定义块匹配一条规则。例如为了匹配自定义块 <foo>

{
+  module: {
+    rules: [
+      {
+        resourceQuery: /blockType=foo/,
+        loader: 'loader-to-use'
+      }
+    ]
+  }
+}
+

如果找到了一个自定义块的匹配规则,它将会被处理,否则该自定义块会被默默忽略。

此外,如果这个自定义块被所有匹配的 loader 处理之后导出一个函数作为最终结果,则这个 *.vue 文件的组件会作为一个参数被这个函数调用。

# Example

这里有一个向组件内注入 <docs> 自定义块的示例,且它是在运行时可用的。

为了注入自定义块的内容,我们将会撰写一个自定义 loader:

module.exports = function (source, map) {
+  this.callback(
+    null,
+    `export default function (Component) {
+      Component.options.__docs = ${
+        JSON.stringify(source)
+      }
+    }`,
+    map
+  )
+}
+

现在我们将会配置 webpack 来使用为 <docs> 自定义块撰写的自定义 loader。

// wepback.config.js
+module.exports = {
+  module: {
+    rules: [
+      {
+        resourceQuery: /blockType=docs/,
+        loader: require.resolve('./docs-loader.js')
+      }
+    ]
+  }
+}
+

现在我们可以在运行时访问被导入组件的 <docs> 块内容了。

<!-- ComponentB.vue -->
+<template>
+  <div>Hello</div>
+</template>
+
+<docs>
+This is the documentation for component B.
+</docs>
+
<!-- ComponentA.vue -->
+<template>
+  <div>
+    <ComponentB/>
+    <p>{{ docs }}</p>
+  </div>
+</template>
+
+<script>
+import ComponentB from './ComponentB.vue';
+
+export default {
+  components: { ComponentB },
+  data () {
+    return {
+      docs: ComponentB.__docs
+    }
+  }
+}
+</script>
+
+ + + diff --git a/vue-loader/zh/guide/extract-css.html b/vue-loader/zh/guide/extract-css.html new file mode 100644 index 000000000..fe527c3ea --- /dev/null +++ b/vue-loader/zh/guide/extract-css.html @@ -0,0 +1,79 @@ + + + + + + CSS 提取 | Vue Loader 中文文档 + + + + + + + +

# CSS 提取

提示

请只在生产环境下使用 CSS 提取,这将便于你在开发环境下进行热重载。

# webpack 4

npm install -D mini-css-extract-plugin
+
// webpack.config.js
+var MiniCssExtractPlugin = require('mini-css-extract-plugin')
+
+module.exports = {
+  // 其它选项...
+  module: {
+    rules: [
+      // ... 忽略其它规则
+      {
+        test: /\.css$/,
+        use: [
+          process.env.NODE_ENV !== 'production'
+            ? 'vue-style-loader'
+            : MiniCssExtractPlugin.loader,
+          'css-loader'
+        ]
+      }
+    ]
+  },
+  plugins: [
+    // ... 忽略 vue-loader 插件
+    new MiniCssExtractPlugin({
+      filename: 'style.css'
+    })
+  ]
+}
+

你还可以查阅 mini-css-extract-plugin 文档

# webpack 3

npm install -D extract-text-webpack-plugin
+
// webpack.config.js
+var ExtractTextPlugin = require("extract-text-webpack-plugin")
+
+module.exports = {
+  // 其它选项...
+  module: {
+    rules: [
+      // ...其它规则忽略
+      {
+        test: /\.css$/,
+        loader: ExtractTextPlugin.extract({
+          use: 'css-loader',
+          fallback: 'vue-style-loader'
+        })
+      }
+    ]
+  },
+  plugins: [
+    // ...vue-loader 插件忽略
+    new ExtractTextPlugin("style.css")
+  ]
+}
+

你也可以查阅 extract-text-webpack-plugin 文档

+ + + diff --git a/vue-loader/zh/guide/functional.html b/vue-loader/zh/guide/functional.html new file mode 100644 index 000000000..b5ccb3327 --- /dev/null +++ b/vue-loader/zh/guide/functional.html @@ -0,0 +1,35 @@ + + + + + + 函数式组件 | Vue Loader 中文文档 + + + + + + + +

# 函数式组件

在一个 *.vue 文件中以单文件形式定义的函数式组件,现在对于模板编译、scoped CSS 和热重载也有了良好的支持。

要声明一个应该编译为函数式组件的模板,请将 functional 特性添加到模板块中。这样做以后就可以省略 <script> 块中的 functional 选项。

模板中的表达式会在函数式渲染上下文中求值。这意味着在模板中,prop 需要以 props.xxx 的形式访问:

<template functional>
+  <div>{{ props.foo }}</div>
+</template>
+

你可以在 parent 上访问 Vue.prototype 全局定义的属性:

<template functional>
+  <div>{{ parent.$someProperty }}</div>
+</template>
+
+ + + diff --git a/vue-loader/zh/guide/hot-reload.html b/vue-loader/zh/guide/hot-reload.html new file mode 100644 index 000000000..464657eab --- /dev/null +++ b/vue-loader/zh/guide/hot-reload.html @@ -0,0 +1,40 @@ + + + + + + 热重载 | Vue Loader 中文文档 + + + + + + + +

# 热重载

“热重载”不只是当你修改文件的时候简单重新加载页面。启用热重载后,当你修改 .vue 文件时,该组件的所有实例将在不刷新页面的情况下被替换。它甚至保持了应用程序和被替换组件的当前状态!当你调整模版或者修改样式时,这极大地提高了开发体验。

hot-reload

# 状态保留规则

  • 当编辑一个组件的 <template> 时,这个组件实例将就地重新渲染,并保留当前所有的私有状态。能够做到这一点是因为模板被编译成了新的无副作用的渲染函数。

  • 当编辑一个组件的 <script> 时,这个组件实例将就地销毁并重新创建。(应用中其它组件的状态将会被保留) 是因为 <script> 可能包含带有副作用的生命周期钩子,所以将重新渲染替换为重新加载是必须的,这样做可以确保组件行为的一致性。这也意味着,如果你的组件带有全局副作用,则整个页面将会被重新加载。

  • <style> 会通过 vue-style-loader 自行热重载,所以它不会影响应用的状态。

# 用法

当使用脚手架工具 vue-cli 时,热重载是开箱即用的。

当手动设置你的工程时,热重载会在你启动 webpack-dev-server --hot 服务时自动开启。

高阶用户可能希望移步 vue-loader 内部使用的 vue-hot-reload-api 继续查阅。

# 关闭热重载

热重载默认是开启的,除非遇到以下情况:

  • webpack 的 target 的值是 node (服务端渲染)
  • webpack 会压缩代码
  • process.env.NODE_ENV === 'production'

你可以设置 hotReload: false 选项来显式地关闭热重载:

module: {
+  rules: [
+    {
+      test: /\.vue$/,
+      loader: 'vue-loader',
+      options: {
+        hotReload: false // 关闭热重载
+      }
+    }
+  ]
+}
+
+ + + diff --git a/vue-loader/zh/guide/index.html b/vue-loader/zh/guide/index.html new file mode 100644 index 000000000..63b0ca42e --- /dev/null +++ b/vue-loader/zh/guide/index.html @@ -0,0 +1,81 @@ + + + + + + 起步 | Vue Loader 中文文档 + + + + + + + +

# 起步

# Vue CLI

如果你不想手动设置 webpack,我们推荐使用 Vue CLI 直接创建一个项目的脚手架。通过 Vue CLI 创建的项目会针对多数常见的开发需求进行预先配置,做到开箱即用。

如果 Vue CLI 提供的内建没有满足你的需求,或者你乐于从零开始创建你自己的 webpack 配置,那么请继续阅读这篇指南。

# 手动设置

# 安装

你应该将 vue-loadervue-template-compiler 一起安装——除非你是使用自行 fork 版本的 Vue 模板编译器的高阶用户:

npm install -D vue-loader vue-template-compiler
+

vue-template-compiler 需要独立安装的原因是你可以单独指定其版本。

每个 vue 包的新版本发布时,一个相应版本的 vue-template-compiler 也会随之发布。编译器的版本必须和基本的 vue 包保持同步,这样 vue-loader 就会生成兼容运行时的代码。这意味着你每次升级项目中的 vue 包时,也应该匹配升级 vue-template-compiler

# webpack 配置

Vue Loader 的配置和其它的 loader 不太一样。除了通过一条规则将 vue-loader 应用到所有扩展名为 .vue 的文件上之外,请确保在你的 webpack 配置中添加 Vue Loader 的插件:

// webpack.config.js
+const VueLoaderPlugin = require('vue-loader/lib/plugin')
+
+module.exports = {
+  module: {
+    rules: [
+      // ... 其它规则
+      {
+        test: /\.vue$/,
+        loader: 'vue-loader'
+      }
+    ]
+  },
+  plugins: [
+    // 请确保引入这个插件!
+    new VueLoaderPlugin()
+  ]
+}
+

这个插件是必须的! 它的职责是将你定义过的其它规则复制并应用到 .vue 文件里相应语言的块。例如,如果你有一条匹配 /\.js$/ 的规则,那么它会应用到 .vue 文件里的 <script> 块。

一个更完整的 webpack 配置示例看起来像这样:

// webpack.config.js
+const VueLoaderPlugin = require('vue-loader/lib/plugin')
+
+module.exports = {
+  mode: 'development',
+  module: {
+    rules: [
+      {
+        test: /\.vue$/,
+        loader: 'vue-loader'
+      },
+      // 它会应用到普通的 `.js` 文件
+      // 以及 `.vue` 文件中的 `<script>` 块
+      {
+        test: /\.js$/,
+        loader: 'babel-loader'
+      },
+      // 它会应用到普通的 `.css` 文件
+      // 以及 `.vue` 文件中的 `<style>` 块
+      {
+        test: /\.css$/,
+        use: [
+          'vue-style-loader',
+          'css-loader'
+        ]
+      }
+    ]
+  },
+  plugins: [
+    // 请确保引入这个插件来施展魔法
+    new VueLoaderPlugin()
+  ]
+}
+

你也可以在选项参考查阅所有可用的 loader 选项。

警告

如果你在开发一个库或多项目仓库 (monorepo),请注意导入 CSS 是具有副作用的。请确保在 package.json移除 "sideEffects": false,否则 CSS 代码块会在生产环境构建时被 webpack 丢掉。

+ + + diff --git a/vue-loader/zh/guide/linting.html b/vue-loader/zh/guide/linting.html new file mode 100644 index 000000000..90342cd6c --- /dev/null +++ b/vue-loader/zh/guide/linting.html @@ -0,0 +1,63 @@ + + + + + + 代码校验 (Linting) | Vue Loader 中文文档 + + + + + + + +

# 代码校验 (Linting)

# ESLint

官方的 eslint-plugin-vue 同时支持在 Vue 单文件组件的模板和脚本部分的代码校验。

请确认在你的 ESLint 配置文件中使用该插件要导入的配置:

// .eslintrc.js
+module.exports = {
+  extends: [
+    "plugin:vue/essential"
+  ]
+}
+

接下来从命令行运行:

eslint --ext js,vue MyComponent.vue
+

另一个选项是使用 eslint-loader 那么你的 *.vue 文件在开发过程中每次保存的时候就会自动进行代码校验:

npm install -D eslint eslint-loader
+

请确保它是作为一个 pre-loader 运用的:

// webpack.config.js
+module.exports = {
+  // ... 其它选项
+  module: {
+    rules: [
+      {
+        enforce: 'pre',
+        test: /\.(js|vue)$/,
+        loader: 'eslint-loader',
+        exclude: /node_modules/
+      }
+    ]
+  }
+}
+

# stylelint

stylelint 支持在 Vue 单文件组件的样式部分的代码校验。

请确认在你的 stylelint 配置文件正确。

接下来从命令行运行:

stylelint MyComponent.vue
+

另一个选项是使用 stylelint-webpack-plugin:

npm install -D stylelint-webpack-plugin
+

请确保它是作为一个插件运用的:

// webpack.config.js
+const StyleLintPlugin = require('stylelint-webpack-plugin');
+module.exports = {
+  // ... 其它选项
+  plugins: [
+    new StyleLintPlugin({
+      files: ['**/*.{vue,htm,html,css,sss,less,scss,sass}'],
+    })
+  ]
+}
+
+ + + diff --git a/vue-loader/zh/guide/pre-processors.html b/vue-loader/zh/guide/pre-processors.html new file mode 100644 index 000000000..33ff08f14 --- /dev/null +++ b/vue-loader/zh/guide/pre-processors.html @@ -0,0 +1,177 @@ + + + + + + 使用预处理器 | Vue Loader 中文文档 + + + + + + + +

# 使用预处理器

在 webpack 中,所有的预处理器需要匹配对应的 loader。Vue Loader 允许你使用其它 webpack loader 处理 Vue 组件的某一部分。它会根据 lang 特性以及你 webpack 配置中的规则自动推断出要使用的 loader。

# Sass

例如,为了通过 Sass/SCSS 编译我们的 <style> 标签:

npm install -D sass-loader node-sass
+

在你的 webpack 配置中:

module.exports = {
+  module: {
+    rules: [
+      // ... 忽略其它规则
+
+      // 普通的 `.scss` 文件和 `*.vue` 文件中的
+      // `<style lang="scss">` 块都应用它
+      {
+        test: /\.scss$/,
+        use: [
+          'vue-style-loader',
+          'css-loader',
+          'sass-loader'
+        ]
+      }
+    ]
+  },
+  // 插件忽略
+}
+

现在,除了能够 import 'style.scss',我们还可以在 Vue 组件中使用 SCSS:

<style lang="scss">
+/* 在这里撰写 SCSS */
+</style>
+

这个块里的任何内容都会被 webpack 当作在一个 *.scss 文件中一样被处理。

# Sass vs SCSS

注意 sass-loader 会默认处理不基于缩进的 scss 语法。为了使用基于缩进的 sass 语法,你需要向这个 loader 传递选项:

// webpack.config.js -> module.rules
+{
+  test: /\.sass$/,
+  use: [
+    'vue-style-loader',
+    'css-loader',
+    {
+      loader: 'sass-loader',
+      options: {
+        indentedSyntax: true,
+        // sass-loader version >= 8
+        sassOptions: {
+          indentedSyntax: true
+        }
+      }
+    }
+  ]
+}
+

# 共享全局变量

sass-loader 也支持一个 prependData 选项,这个选项允许你在所有被处理的文件之间共享常见的变量,而不需要显式地导入它们:

// webpack.config.js -> module.rules
+{
+  test: /\.scss$/,
+  use: [
+    'vue-style-loader',
+    'css-loader',
+    {
+      loader: 'sass-loader',
+      options: {
+        // 你也可以从一个文件读取,例如 `variables.scss`
+        // 如果 sass-loader 版本 < 8,这里使用 `data` 字段
+        prependData: `$color: red;`
+      }
+    }
+  ]
+}
+

# Less

npm install -D less less-loader
+
// webpack.config.js -> module.rules
+{
+  test: /\.less$/,
+  use: [
+    'vue-style-loader',
+    'css-loader',
+    'less-loader'
+  ]
+}
+

# Stylus

npm install -D stylus stylus-loader
+
// webpack.config.js -> module.rules
+{
+  test: /\.styl(us)?$/,
+  use: [
+    'vue-style-loader',
+    'css-loader',
+    'stylus-loader'
+  ]
+}
+

# PostCSS

TIP

Vue Loader v15 不再默认应用 PostCSS 变换。你需要通过 postcss-loader 使用 PostCSS。

npm install -D postcss-loader
+
// webpack.config.js -> module.rules
+{
+  test: /\.css$/,
+  use: [
+    'vue-style-loader',
+    {
+      loader: 'css-loader',
+      options: { importLoaders: 1 }
+    },
+    'postcss-loader'
+  ]
+}
+

PostCSS 的配置可以通过 postcss.config.jspostcss-loader 选项来完成。其更多细节请查阅 postcss-loader 文档

postcss-loader 也可以和上述其它预处理器结合使用。

# Babel

npm install -D babel-core babel-loader
+
// webpack.config.js -> module.rules
+{
+  test: /\.js?$/,
+  loader: 'babel-loader'
+}
+

Babel 的配置可以通过 .babelrcbabel-loader 选项来完成。

# 排除 node_modules

exclude: /node_modules/ 在应用于 .js 文件的 JS 转译规则 (例如 babel-loader) 中是蛮常见的。鉴于 v15 中的推导变化,如果你导入一个 node_modules 内的 Vue 单文件组件,它的 <script> 部分在转译时将会被排除在外。

为了确保 JS 的转译应用到 node_modules 的 Vue 单文件组件,你需要通过使用一个排除函数将它们加入白名单:

{
+  test: /\.js$/,
+  loader: 'babel-loader',
+  exclude: file => (
+    /node_modules/.test(file) &&
+    !/\.vue\.js/.test(file)
+  )
+}
+

# TypeScript

npm install -D typescript ts-loader
+
// webpack.config.js
+module.exports = {
+  resolve: {
+    // 将 `.ts` 添加为一个可解析的扩展名。
+    extensions: ['.ts', '.js']
+  },
+  module: {
+    rules: [
+      // ... 忽略其它规则
+      {
+        test: /\.ts$/,
+        loader: 'ts-loader',
+        options: { appendTsSuffixTo: [/\.vue$/] }
+      }
+    ]
+  },
+  // ...plugin omitted
+}
+

TypeScript 的配置可以通过 tsconfig.json 来完成。你也可以查阅 ts-loader 的文档。

# Pug

模板的处理会稍微有些不同,因为绝大多数 webpack 的模板类 loader,诸如 pug-loader,会返回一个模板函数而不是一个编译好的 HTML 字符串。所以我们需要使用一个返回原始的 HTML 字符串的 loader,例如 pug-plain-loader,而不是使用 pug-loader

npm install -D pug pug-plain-loader
+
// webpack.config.js -> module.rules
+{
+  test: /\.pug$/,
+  loader: 'pug-plain-loader'
+}
+

然后你可以写:

<template lang="pug">
+div
+  h1 Hello world!
+</template>
+

如果你还打算使用它在 JavaScript 中将 .pug 文件作为字符串导入,你需要在这个预处理 loader 之后链上 raw-loader。注意添加 raw-loader 会破坏 Vue 组件内的用法,所以你需要定义两条规则,其中一条指向使用了一个 resourceQuery 的 Vue 文件,另一条指向 (回退到) JavaScript 导入:

// webpack.config.js -> module.rules
+{
+  test: /\.pug$/,
+  oneOf: [
+    // 这条规则应用到 Vue 组件内的 `<template lang="pug">`
+    {
+      resourceQuery: /^\?vue/,
+      use: ['pug-plain-loader']
+    },
+    // 这条规则应用到 JavaScript 内的 pug 导入
+    {
+      use: ['raw-loader', 'pug-plain-loader']
+    }
+  ]
+}
+
+ + + diff --git a/vue-loader/zh/guide/scoped-css.html b/vue-loader/zh/guide/scoped-css.html new file mode 100644 index 000000000..d74afd0eb --- /dev/null +++ b/vue-loader/zh/guide/scoped-css.html @@ -0,0 +1,58 @@ + + + + + + Scoped CSS | Vue Loader 中文文档 + + + + + + + +

# Scoped CSS

<style> 标签有 scoped 属性时,它的 CSS 只作用于当前组件中的元素。这类似于 Shadow DOM 中的样式封装。它有一些注意事项,但不需要任何 polyfill。它通过使用 PostCSS 来实现以下转换:

<style scoped>
+.example {
+  color: red;
+}
+</style>
+
+<template>
+  <div class="example">hi</div>
+</template>
+

转换结果:

<style>
+.example[data-v-f3f3eg9] {
+  color: red;
+}
+</style>
+
+<template>
+  <div class="example" data-v-f3f3eg9>hi</div>
+</template>
+

# 混用本地和全局样式

你可以在一个组件中同时使用有 scoped 和非 scoped 样式:

<style>
+/* 全局样式 */
+</style>
+
+<style scoped>
+/* 本地样式 */
+</style>
+

# 子组件的根元素

使用 scoped 后,父组件的样式将不会渗透到子组件中。不过一个子组件的根节点会同时受其父组件的 scoped CSS 和子组件的 scoped CSS 的影响。这样设计是为了让父组件可以从布局的角度出发,调整其子组件根元素的样式。

# 深度作用选择器

如果你希望 scoped 样式中的一个选择器能够作用得“更深”,例如影响子组件,你可以使用 >>> 操作符:

<style scoped>
+.a >>> .b { /* ... */ }
+</style>
+

上述代码将会编译成:

.a[data-v-f3f3eg9] .b { /* ... */ }
+

有些像 Sass 之类的预处理器无法正确解析 >>>。这种情况下你可以使用 /deep/::v-deep 操作符取而代之——两者都是 >>> 的别名,同样可以正常工作。

# 动态生成的内容

通过 v-html 创建的 DOM 内容不受 scoped 样式影响,但是你仍然可以通过深度作用选择器来为他们设置样式。

# 还有一些要留意

  • Scoped 样式不能代替 class。考虑到浏览器渲染各种 CSS 选择器的方式,当 p { color: red } 是 scoped 时 (即与特性选择器组合使用时) 会慢很多倍。如果你使用 class 或者 id 取而代之,比如 .example { color: red },性能影响就会消除。你可以在这块试验田中测试它们的不同。

  • 在递归组件中小心使用后代选择器! 对选择器 .a .b 中的 CSS 规则来说,如果匹配 .a 的元素包含一个递归子组件,则所有的子组件中的 .b 都将被这个规则匹配。

+ + + diff --git a/vue-loader/zh/guide/testing.html b/vue-loader/zh/guide/testing.html new file mode 100644 index 000000000..84a649cf8 --- /dev/null +++ b/vue-loader/zh/guide/testing.html @@ -0,0 +1,25 @@ + + + + + + 测试 | Vue Loader 中文文档 + + + + + + + +

# 测试

  • Vue CLI 提供了预配置的单元测试和 e2e 测试安装。

  • 如果你有兴趣为 *.vue 文件手动设置单元测试,请查询 @vue/test-utils 的文档,这份文档涵盖了对 mocha-webpackJest 的设置。

+ + + diff --git a/vue-loader/zh/index.html b/vue-loader/zh/index.html new file mode 100644 index 000000000..e574c6274 --- /dev/null +++ b/vue-loader/zh/index.html @@ -0,0 +1,44 @@ + + + + + + 介绍 | Vue Loader 中文文档 + + + + + + + +

# 介绍

版本说明

这份文档是为 Vue Loader v15 及以上版本撰写的。如果你正在从 v14 或更早的版本往这里迁移,请查阅迁移指南。如果你正在使用老版本,其对应的文档在此

# Vue Loader 是什么?

Vue Loader 是一个 webpack 的 loader,它允许你以一种名为单文件组件 (SFCs)的格式撰写 Vue 组件:

<template>
+  <div class="example">{{ msg }}</div>
+</template>
+
+<script>
+export default {
+  data () {
+    return {
+      msg: 'Hello world!'
+    }
+  }
+}
+</script>
+
+<style>
+.example {
+  color: red;
+}
+</style>
+

Vue Loader 还提供了很多酷炫的特性:

  • 允许为 Vue 组件的每个部分使用其它的 webpack loader,例如在 <style> 的部分使用 Sass 和在 <template> 的部分使用 Pug;
  • 允许在一个 .vue 文件中使用自定义块,并对其运用自定义的 loader 链;
  • 使用 webpack loader 将 <style><template> 中引用的资源当作模块依赖来处理;
  • 为每个组件模拟出 scoped CSS;
  • 在开发过程中使用热重载来保持状态。

简而言之,webpack 和 Vue Loader 的结合为你提供了一个现代、灵活且极其强大的前端工作流,来帮助撰写 Vue.js 应用。

+ + + diff --git a/vue-loader/zh/migrating.html b/vue-loader/zh/migrating.html new file mode 100644 index 000000000..cf1b159c8 --- /dev/null +++ b/vue-loader/zh/migrating.html @@ -0,0 +1,160 @@ + + + + + + 从 v14 迁移 | Vue Loader 中文文档 + + + + + + + +

# 从 v14 迁移

注意

我们正在升级 Vue CLI 3 beta 的过程中,并使用了 webpack 4 + Vue Loader v15,所以如果你计划升级到 Vue CLI 3 的话,可能需要等待。

# 值得注意的不兼容变更

# 现在你需要一个插件

Vue Loader v15 现在需要配合一个 webpack 插件才能正确使用:

// webpack.config.js
+const VueLoaderPlugin = require('vue-loader/lib/plugin')
+
+module.exports = {
+  // ...
+  plugins: [
+    new VueLoaderPlugin()
+  ]
+}
+

# Loader 推导

现在 Vue Loader v15 使用了一个不一样的策略来推导语言块使用的 loader。

<style lang="less"> 举例:在 v14 或更低版本中,它会尝试使用 less-loader 加载这个块,并在其后面隐式地链上 css-loadervue-style-loader,这一切都使用内联的 loader 字符串。

在 v15 中,<style lang="less"> 会完成把它当作一个真实的 *.less 文件来加载。因此,为了这样处理它,你需要在你的主 webpack 配置中显式地提供一条规则:

{
+  module: {
+    rules: [
+      // ... 其它规则
+      {
+        test: /\.less$/,
+        use: [
+          'vue-style-loader',
+          'css-loader',
+          'less-loader'
+        ]
+      }
+    ]
+  }
+}
+

这样做的好处是这条规则同样应用在 JavaScript 里普通的 *.less 导入中,并且你可以为这些 loader 配置任何你想要的选项。在 v14 或更低版本中,如果你想为一个推导出来的 loader 定制选项,你不得不在 Vue Loader 自己的 loaders 选项中将它重复一遍。在 v15 中你再也没有必要这么做了。

v15 也允许为 loader 使用非序列化的选项,这种选项在之前的版本中是无法使用的。

# 从依赖中导入单文件组件

exclude: /node_modules/ 在运用于 .js 文件的 JS 转译规则 (例如 babel-loader) 中是蛮常见的。鉴于 v15 中的推导变化,如果你导入一个 node_modules 内的 Vue 单文件组件,它的 <script> 部分在转译时将会被排除在外。

为了确保 JS 的转译应用到 node_modules 的 Vue 单文件组件,你需要通过使用一个排除函数将它们加入白名单:

{
+  test: /\.js$/,
+  loader: 'babel-loader',
+  exclude: file => (
+    /node_modules/.test(file) &&
+    !/\.vue\.js/.test(file)
+  )
+}
+

# 模板预处理

v14 或更低版本使用 consolidate 来编译 <template lang="xxx">。v15 现在取而代之的是使用 webpack loader 为它们应用预处理器。

注意有些模板的 loader 会导出一个编译好的模板函数而不是普通的 HTML,诸如 pug-loader。为了向 Vue 的模板编译器传递正确的内容,你必须换用一个输出普通 HTML 的 loader。例如,为了支持 <template lang="pug">,你可以使用 pug-plain-loader

{
+  module: {
+    rules: [
+      {
+        test: /\.pug$/,
+        loader: 'pug-plain-loader'
+      }
+    ]
+  }
+}
+

如果你还打算使用它在 JavaScript 中将 .pug 文件作为字符串导入,你需要在这个预处理 loader 之后链上 raw-loader。注意添加 raw-loader 会破坏 Vue 组件内的用法,所以你需要定义两条规则,其中一条指向使用了一个 resourceQuery 的 Vue 文件,另一条指向 (回退到) JavaScript 导入:

{
+  module: {
+    rules: [
+      {
+        test: /\.pug$/,
+        oneOf: [
+          // 这条规则应用到 Vue 组件内的 `<template lang="pug">`
+          {
+            resourceQuery: /^\?vue/,
+            use: ['pug-plain-loader']
+          },
+          // 这条规则应用到 JavaScript 内的 pug 导入
+          {
+            use: ['raw-loader', 'pug-plain-loader']
+          }
+        ]
+      }
+    ]
+  }
+}
+

# 样式注入

现在客户端的样式注入会在最前面注入所有的样式以确保开发模式和提取模式下行为的一致性。

注意它们注入的顺序是不能保证的,所以你撰写的 CSS 应该避免依赖插入的顺序。

# PostCSS

Vue Loader v15 不再默认应用 PostCSS 变换。想要使用 PostCSS,请像配置普通 CSS 文件那样配置 postcss-loader

# CSS Modules

CSS Modules 现在需要通过 css-loader 选项显式地配置。<style> 标签上的 module 特性仍然需要用来局部注入到组件中。

好消息是你现在可以在同一处配置 localIdentName 了:

{
+  module: {
+    rules: [
+      {
+        test: /\.css$/,
+        use: [
+          {
+            loader: 'vue-style-loader'
+          },
+          {
+            loader: 'css-loader',
+            options: {
+              modules: true,
+              localIdentName: '[local]_[hash:base64:8]'
+            }
+          }
+        ]
+      }
+    ]
+  }
+}
+

如果你只想在某些 Vue 组件中使用 CSS Modules,你可以使用 oneOf 规则并在 resourceQuery 字符串中检查 module 字符串:

{
+  test: /\.css$/,
+  oneOf: [
+    // 这里匹配 `<style module>`
+    {
+      resourceQuery: /module/,
+      use: [
+        'vue-style-loader',
+        {
+          loader: 'css-loader',
+          options: {
+            modules: true,
+            localIdentName: '[local]_[hash:base64:5]'
+          }
+        }
+      ]
+    },
+    // 这里匹配普通的 `<style>` 或 `<style scoped>`
+    {
+      use: [
+        'vue-style-loader',
+        'css-loader'
+      ]
+    }
+  ]
+}
+

# CSS 提取

用法和你为普通 CSS 的配置一样。示例用法在 mini-css-extract-plugin

{
+  module: {
+    rules: [
+      {
+        test: /\.vue$/,
+        use: 'vue-loader'
+      },
+      {
+        test: /\.css$/,
+        // 或 `ExtractTextWebpackPlugin.extract(...)`
+        use: [
+          MiniCssExtractPlugin.loader,
+          'css-loader'
+        ]
+      }
+    ]
+  },
+  plugins: [
+    new MiniCssExtractPlugin({
+      filename: 'output.css'
+    })
+  ]
+}
+

# 服务端渲染的依赖排除

在服务端渲染中,我们通常使用 webpack-node-externals 来从服务端构建中排除 npm 依赖。如果你需要从一个 npm 依赖导入 CSS,之前的方案是使用像这样的一个白名单:

// webpack 配置
+externals: nodeExternals({
+  whitelist: /\.css$/
+})
+

使用 v15,导入 <style src="dep/foo.css"> 现在会在请求的末尾追加 resourceQuery 字符串,所以你需要将上述内容更新为:

externals: nodeExternals({
+  whitelist: [/\.css$/, /\?vue&type=style/]
+})
+

# 废弃的选项

下列选项已经被废弃了,它们应该使用普通的 webpack 模块的规则来配置:

  • loader
  • preLoaders
  • postLoaders
  • postcss
  • cssSourceMap
  • buble
  • extractCSS
  • template

下列选项已经被废弃了,它们应该使用新的 compilerOptions 选项来配置:

  • preserveWhitespace (使用 compilerOptions.preserveWhitespace)
  • compilerModules (使用 compilerOptions.modules)
  • compilerDirectives (使用 compilerOptions.directives)

下列选项已经被改名了:

  • transformToRequire (现在改名为 transformAssetUrls)

TIP

想查阅新选项的完整列表,请移步选项参考

+ + + diff --git a/vue-loader/zh/options.html b/vue-loader/zh/options.html new file mode 100644 index 000000000..8d579d461 --- /dev/null +++ b/vue-loader/zh/options.html @@ -0,0 +1,29 @@ + + + + + + 选项参考 | Vue Loader 中文文档 + + + + + + + +

# 选项参考

# transformAssetUrls

  • 类型:{ [tag: string]: string | Array<string> }

  • 默认值:

    {
    +  video: ['src', 'poster'],
    +  source: 'src',
    +  img: 'src',
    +  image: ['xlink:href', 'href'],
    +  use: ['xlink:href', 'href']
    +}
    +

    在模板编译过程中,编译器可以将某些特性转换为 require 调用,例如 src 中的 URL。因此这些目标资源可以被 webpack 处理。例如 <img src="./foo.png"> 会找到你文件系统中的 ./foo.png 并将其作为一个依赖包含在你的包里。

# compiler

  • 类型:VueTemplateCompiler

  • 默认值:require('vue-template-compiler')

    覆写用来编译单文件组件中 <template> 块的默认编译器。

# compilerOptions

  • 类型:Object

  • 默认值:{}

    模板编译器的选项。当使用默认的 vue-template-compiler 的时候,你可以使用这个选项来添加自定义编译器指令、模块或通过 { preserveWhitespace: false } 放弃模板标签之间的空格。

    详情查阅 vue-template-compiler 选项参考.

# transpileOptions

  • 类型:Object

  • 默认值:{}

    为渲染函数的生成码配置从 ES2015+ 到 ES5 的转译选项。这里的转译器是一份 Buble 的 fork,因此你可以在这里查阅可用的选项。

    模板渲染函数编译支持一个特殊的变换 stripWith (默认启用),它会删除生成的渲染函数中的 with 用法,使它们兼容严格模式。

# optimizeSSR

  • 类型:boolean

  • 默认值:当 webpack 配置中包含 target: 'node'vue-template-compiler 版本号大于等于 2.4.0 时为 true

    开启 Vue 2.4 服务端渲染的编译优化之后,渲染函数将会把返回的 vdom 树的一部分编译为字符串,以提升服务端渲染的性能。在一些情况下,你可能想要明确地将其关掉,因为该渲染函数只能用于服务端渲染,而不能用于客户端渲染或测试环境。

# hotReload

  • 类型:boolean

  • 默认值:在开发环境下是 true,在生产环境下或 webpack 配置中有 target: 'node' 的时候是 false

  • 允许的值:false (true 会强制热重载,即便是生产环境或 target: 'node' 时)

    是否使用 webpack 的模块热替换在浏览器中应用变更而不重载整个页面。 +用这个选项 (值设为 false) 在开发环境下关闭热重载特性。

# productionMode

  • 类型:boolean
  • 默认值:process.env.NODE_ENV === 'production'

强制指定为生产环境,即禁止 loader 注入只在开发环境有效的代码 (例如 hot-reload 相关的代码)。

# shadowMode

  • 类型:boolean
  • 默认值:false

编译用于 Shadow DOM 内部的组件。在该模式下,组件的样式会被注入到 this.$root.$options.shadowRoot,而不是文档的 head 部分。

# cacheDirectory / cacheIdentifier

  • 类型:string
  • 默认值:undefined

当这两个选项同时被设置时,开启基于文件系统的模板编译缓存 (需要在工程里安装 cache-loader)。

注意

在内部,vue-loadercache-loader 之间的交互使用了 loader 的内联 import 语法! 将会被认为是不同 loaders 之间的分隔符,所以请确保你的 cacheDirectory 路径中不包含 !

# prettify

  • 类型:boolean
  • 默认值:true

在开发环境下,我们默认使用 prettier 格式化编译后的模板渲染代码,以方便调试。然而,如果你开发时碰到了 prettier 的某些罕见 bug,比如格式化多层嵌套的函数时运行时间过长,你可以通过禁用这个选项来绕开。

# exposeFilename

  • 类型:boolean
  • 默认值:false

在非生产环境下,vue-loader 会为组件注入一个 __file 属性以提升调试体验。如果一个组件没有 name 属性,Vue 会通过 __file 字段进行推断,并用于控制台警告中的展示。

这个属性在生产环境构建时会被去掉。但如果你在开发一个组件库并且烦于为每个组件设置 name,你可能还会想使用它。这时可以把这个选项打开。

+ + + diff --git a/vue-loader/zh/spec.html b/vue-loader/zh/spec.html new file mode 100644 index 000000000..d85bd9ae3 --- /dev/null +++ b/vue-loader/zh/spec.html @@ -0,0 +1,54 @@ + + + + + + 单文件组件规范 | Vue Loader 中文文档 + + + + + + + +

# Vue 单文件组件 (SFC) 规范

# 简介

.vue 文件是一个自定义的文件类型,用类 HTML 语法描述一个 Vue 组件。每个 .vue 文件包含三种类型的顶级语言块 <template><script><style>,还允许添加可选的自定义块:

<template>
+  <div class="example">{{ msg }}</div>
+</template>
+
+<script>
+export default {
+  data () {
+    return {
+      msg: 'Hello world!'
+    }
+  }
+}
+</script>
+
+<style>
+.example {
+  color: red;
+}
+</style>
+
+<custom1>
+  This could be e.g. documentation for the component.
+</custom1>
+

vue-loader 会解析文件,提取每个语言块,如有必要会通过其它 loader 处理,最后将他们组装成一个 ES Module,它的默认导出是一个 Vue.js 组件选项的对象。

vue-loader 支持使用非默认语言,比如 CSS 预处理器,预编译的 HTML 模版语言,通过设置语言块的 lang 属性。例如,你可以像下面这样使用 Sass 语法编写样式:

<style lang="sass">
+  /* write Sass! */
+</style>
+

更多细节可以在使用预处理器中找到。

# 语言块

# 模板

  • 每个 .vue 文件最多包含一个 <template> 块。

  • 内容将被提取并传递给 vue-template-compiler 为字符串,预处理为 JavaScript 渲染函数,并最终注入到从 <script> 导出的组件中。

# 脚本

  • 每个 .vue 文件最多包含一个 <script> 块。

  • 这个脚本会作为一个 ES Module 来执行。

  • 它的默认导出应该是一个 Vue.js 的组件选项对象。也可以导出由 Vue.extend() 创建的扩展对象,但是普通对象是更好的选择。

  • 任何匹配 .js 文件 (或通过它的 lang 特性指定的扩展名) 的 webpack 规则都将会运用到这个 <script> 块的内容中。

# 样式

  • 默认匹配:/\.css$/

  • 一个 .vue 文件可以包含多个 <style> 标签。

  • <style> 标签可以有 scoped 或者 module 属性 (查看 scoped CSSCSS Modules) 以帮助你将样式封装到当前组件。具有不同封装模式的多个 <style> 标签可以在同一个组件中混合使用。

  • 任何匹配 .css 文件 (或通过它的 lang 特性指定的扩展名) 的 webpack 规则都将会运用到这个 <style> 块的内容中。

# 自定义块

可以在 .vue 文件中添加额外的自定义块来实现项目的特定需求,例如 <docs> 块。vue-loader 将会使用标签名来查找对应的 webpack loader 来应用在对应的块上。webpack loader 需要在 vue-loader 的选项 loaders 中指定。

更多细节,查看自定义块

# Src 导入

如果喜欢把 .vue 文件分隔到多个文件中,你可以通过 src 属性导入外部文件:

<template src="./template.html"></template>
+<style src="./style.css"></style>
+<script src="./script.js"></script>
+

需要注意的是 src 导入遵循和 webpack 模块请求相同的路径解析规则,这意味着:

  • 相对路径需要以 ./ 开始
  • 你可以从 NPM 依赖中导入资源:
<!-- import a file from the installed "todomvc-app-css" npm package -->
+<style src="todomvc-app-css/index.css">
+

在自定义块上同样支持 src 导入,例如:

<unit-test src="./unit-test.js">
+</unit-test>
+

# 语法高亮 / IDE 支持

目前有下列 IDE/编辑器 支持语法高亮:

非常感谢其他编辑器/IDE 所做的贡献!如果在 Vue 组件中没有使用任何预处理器,你可以把 .vue 文件当作 HTML 对待。

# 注释

在语言块中使用该语言块对应的注释语法 (HTML、CSS、JavaScript、Jade 等)。顶层注释使用 HTML 注释语法:<!-- comment contents here -->

+ + + diff --git a/yarn.lock b/yarn.lock index 445f209df..4d1049b76 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11428,10 +11428,10 @@ vuepress-html-webpack-plugin@^3.2.0: toposort "^1.0.0" util.promisify "1.0.0" -vuepress-theme-vue@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/vuepress-theme-vue/-/vuepress-theme-vue-1.1.0.tgz#8b109e3db8cad7b18459f4d77076808110c2bcaa" - integrity sha512-oYbfWkeaQ6aUU8sl8fMzLnBnvsd23V0wkiqI0bR3Tq3mlI8EJu26PFOyyF7KvJu0qNo/lcL7CDSmX7ymUVpnvw== +vuepress-theme-docmirror@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/vuepress-theme-docmirror/-/vuepress-theme-docmirror-1.1.1.tgz#8bd68c64c99e671d9fa668137a7935da7d2d2483" + integrity sha512-6xGTpp0mhRHOK2pVmxXmG1wjZkv6RKUlIBn2RuWXu6HjJE0CaYhb7tYxb6WaHUOYFKcOe68xml+70cW2CAhlLw== vuepress@^0.14.2: version "0.14.11"