이번에는 Vue 멀티 페이지 개발 및 패키징 사용법을 보여드리고, Vue 멀티 페이지 개발 및 패키징 사용 시 주의사항은 무엇인지 살펴보겠습니다.
얼마전 기술스택을 진행하고 있었는데 주로 공식 홈페이지와 백엔드 관리 시스템을 당시 상황을 토대로 3가지 솔루션을 분석해봤습니다
하나의 프로젝트 코드에는 두 개의 스파 애플리케이션이 내장되어 있습니다(공식 웹사이트 및 백엔드 시스템)
두 세트의 프로젝트 소스 코드를 분리합니다
한 프로젝트 소스 코드 세트에는 하나의 스파 애플리케이션만 있습니다
생각:
한 세트의 프로젝트 소스 코드에서 하나의 스파 애플리케이션(ui)을 직접 무효화합니다. 스타일이 서로를 덮게 되며, 코드 사양이 없으면 나중에 유지 관리가 어렵습니다)
있다면 소스 코드가 2개 세트인데, 백그라운드에서 2개의 포트가 열려서 nginx 리버스 프록시를 사용하는 것도 번거로울 수 있고, 프론트엔드 개발도 결국 2개의 git 웨어하우스와 2개의 git 온라인 프로세스가 번거로울 수 있습니다. 유지 관리가 필요하므로 많은 시간이 소요될 수 있습니다.
나는 (무의식적으로) 내 기술에 자신감이 있고 새로운 것을 시도하고 싶다. 요구사항을 분석하는 것은 그리 복잡하지 않다. 하나의 소스 코드 세트에서 여러 단일 페이지 애플리케이션을 사용하는 첫 번째 옵션을 선택했습니다.
이전 다중 페이지 구조 다이어그램
vue spa 템플릿 다운로드
npm install vue-cli -g vue init webpack multiple-vue-amazing
멀티 변환 -page application
npm install glob --save-dev
src 폴더 아래 디렉터리 구조 수정
Add
/* 这里是添加的部分 ---------------------------- 开始 */ // glob是webpack安装时依赖的一个第三方模块,还模块允许你使用 *等符号, 例如lib/*.js就是获取lib文件夹下的所有js后缀名的文件 var glob = require('glob') // 页面模板 var HtmlWebpackPlugin = require('html-webpack-plugin') // 取得相应的页面路径,因为之前的配置,所以是src文件夹下的pages文件夹 var PAGE_PATH = path.resolve(__dirname, '../src/pages') // 用于做相应的merge处理 var merge = require('webpack-merge') //多入口配置 // 通过glob模块读取pages文件夹下的所有对应文件夹下的js后缀文件,如果该文件存在 // 那么就作为入口处理 exports.entries = function () { var entryFiles = glob.sync(PAGE_PATH + '/*/*.js') var map = {} entryFiles.forEach((filePath) => { var filename = filePath.substring(filePath.lastIndexOf('\/') + 1, filePath.lastIndexOf('.')) map[filename] = filePath }) return map } //多页面输出配置 // 与上面的多页面入口配置相同,读取pages文件夹下的对应的html后缀文件,然后放入数组中 exports.htmlPlugin = function () { let entryHtml = glob.sync(PAGE_PATH + '/*/*.html') let arr = [] entryHtml.forEach((filePath) => { let filename = filePath.substring(filePath.lastIndexOf('\/') + 1, filePath.lastIndexOf('.')) let conf = { // 模板来源 template: filePath, // 文件名称 filename: filename + '.html', // 页面模板需要加对应的js脚本,如果不加这行则每个页面都会引入所有的js脚本 chunks: ['manifest', 'vendor', filename], inject: true } if (process.env.NODE_ENV === 'production') { conf = merge(conf, { minify: { removeComments: true, collapseWhitespace: true, removeAttributeQuotes: true }, chunksSortMode: 'dependency' }) } arr.push(new HtmlWebpackPlugin(conf)) }) return arr } /* 这里是添加的部分 ---------------------------- 结束 */ webpack.base.conf.js 文件 /* 修改部分 ---------------- 开始 */ entry: utils.entries(), /* 修改部分 ---------------- 结束 */ webpack.dev.conf.js 文件 /* 注释这个区域的文件 ------------- 开始 */ // new HtmlWebpackPlugin({ // filename: 'index.html', // template: 'index.html', // inject: true // }), /* 注释这个区域的文件 ------------- 结束 */ new FriendlyErrorsPlugin() /* 添加 .concat(utils.htmlPlugin()) ------------------ */ ].concat(utils.htmlPlugin()) webpack.prod.conf.js 文件 /* 注释这个区域的内容 ---------------------- 开始 */ // new HtmlWebpackPlugin({ // filename: config.build.index, // template: 'index.html', // inject: true, // minify: { // removeComments: true, // collapseWhitespace: true, // removeAttributeQuotes: true // // more options: // // https://github.com/kangax/html-minifier#options-quick-reference // }, // // necessary to consistently work with multiple chunks via CommonsChunkPlugin // chunksSortMode: 'dependency' // }), /* 注释这个区域的内容 ---------------------- 结束 */ // copy custom static assets new CopyWebpackPlugin([ { from: path.resolve(__dirname, '../static'), to: config.build.assetsSubDirectory, ignore: ['.*'] } ]) /* 该位置添加 .concat(utils.htmlPlugin()) ------------------- */ ].concat(utils.htmlPlugin())
util.js에 타사 UI 라이브러리 소개
npm install element-ui bootstrap-vue --save
다른 페이지에 다른 ui index.js 소개
import BootstrapVue from 'bootstrap-vue' Vue.use(BootstrapVue)
admin .js
import ElementUI from 'element-ui' import 'element-ui/lib/theme-chalk/index.css' Vue.use(ElementUI)
위의 다중 페이지 구성은 인터넷을 기반으로 하며 인터넷에 있는 아이디어는 대부분 유사하며 구성이 완료된 후에는 개발 중에 문제가 발견되지 않습니다. 개발에 약 한 달 정도 걸렸는데, 개발 후 공식 홈페이지에서 성능 분석을 해보니 webpack으로 패키징한 Vendor.js의 네트워크 로딩 시간이 특히 길어서 화이트 스크린 시간이 매우 길어지는 것으로 나타났습니다. 마지막으로 -webpack-bundle-analyzer 분석을 통해 결론을 얻었습니다
npm run build --report
vendor.js에는 index.html과 admin.html의 공통 부분이 포함되어 있으므로 이 공급업체 패키지는 다음과 같습니다. be big and redundant
Solution
로드 속도는 벤더가 너무 커서 발생하므로 느리다면 벤더를 분리하면 됩니다. 제 생각에는 각 페이지에 사용된 타사 코드를 Vendor.js로 추출한 다음, 각 페이지에 사용된 타사 코드를 기존 페이지 인덱스 .html과 같은 자체 Vendor-x.js로 패키징하는 것입니다. , admin.html, Vendor.js, Vendor-index.js, Vendor-admin.js가 최종적으로 패키징됩니다.
webpack.prod.conf.js 파일
new webpack.optimize.CommonsChunkPlugin({ name: 'vendor-admin', chunks: ['vendor'], minChunks: function (module, count) { return ( module.resource && /\.js$/.test(module.resource) && module.resource.indexOf(path.join(__dirname, '../node_modules')) === 0 && module.resource.indexOf('element-ui') != -1 ) } }), new webpack.optimize.CommonsChunkPlugin({ name: 'vendor-index', chunks: ['vendor'], minChunks: function (module, count) { return ( module.resource && /\.js$/.test(module.resource) && module.resource.indexOf(path.join(__dirname, '../node_modules')) === 0 && module.resource.indexOf('bootstrap-vue') != -1 ) } }),
다시 분석해 보니 모든 것이 괜찮습니다. Vendor.js는 Vendor.js, Vendor-index, Vendor-admin.js
로 분리되어 있습니다.
해결된 줄 알았는데 CommonsChunkPlugin 그런 다음 이를 패키지화하여 index.html과 admin.html에 가져오기(해당 Vendor-xx.js)가 누락되었음을 확인합니다.
Solution
문제는 실제로 HtmlWebpackPlugin의 문제입니다. 다음과 같이 원래의 ChunsSortMode: 'dependent'를 사용자 정의 함수의 구성으로 변경합니다.
util.js 파일
chunksSortMode: function (chunk1, chunk2) { var order1 = chunks.indexOf(chunk1.names[0]) var order2 = chunks.indexOf(chunk2.names[0]) return order1 - order2 },
최종적으로 구현됨
각 페이지는 자체 청크를 로드합니다
각 페이지에는 서로 다른 매개변수가 있습니다.
각 페이지는 공통 청크를 공유할 수 있습니다
브라우저 캐싱, 성능 향상
그래도 너무 느리다면 gzip을 켜보세요
Impressions
다 구성이 아주 간단해 보이지만, 개발할 때 생각한 게 있어요. 오랜만이라 CommonsChunkPlugin과 HtmlWebpackPlugin에 익숙하지 않거나 다른 타사 구성 테이블만 사용하는 경우 문제가 발생할 수 있습니다. 예를 들어 CommonsChunkPlugin에서 청크를 지정하지 않으면 기본값은 무엇입니까? minChunks에 있는 대부분의 사람들은 단일 값만 쓸 수 있지만 실제로는 사용자 정의 함수를 작성하는 방법이 가장 강력합니다. 내 개인적인 경험에 따르면 minChunks 사용자 정의 함수와 결합된 청크를 작성하는 방법은 거의 모든 초자연적인 사건을 해결할 수 있습니다. CommonsChunkPlugin.
이 기사의 사례를 읽은 후 방법을 마스터했다고 생각합니다. 더 흥미로운 정보를 보려면 PHP 중국어 웹사이트의 다른 관련 기사를 주목하세요!
추천 자료:
vue.js+element-ui 메뉴 트리 구조 만들기
위 내용은 Vue 다중 페이지 개발 및 패키징을 사용하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!