Vue2+Symfony Webpack:Editor组件特定页面按需加载实现
整个调整过程不需要改动现有全局Vue实例的运行逻辑,仅通过拆分入口、剥离依赖的方式即可实现Editor组件的按需加载,所有代码都和Symfony默认的Encore配置兼容,不需要额外编写复杂的Webpack规则。
第一步:清理公共入口app.js的无关依赖
直接把app.js里所有和Editor组件相关的引用、注册逻辑移除,让app.js回到纯公共业务逻辑的状态,从根源上避免CKEditor的代码被打进公共包:
// assets/app.js(调整后) import Vue from 'vue'; // 移除所有Editor相关的import、组件注册逻辑 new Vue({ el: '#app', components: { // 这里只保留其他全局需要的公共组件 } });
第二步:调整Editor组件的DOM获取逻辑
原组件里存在两处可优化的问题:一是硬编码通过document.querySelector('#editor')获取DOM,多实例场景下会出现id冲突;二是给ClassicEditor.create传配置参数时漏写了配置对象的包裹大括号,存在语法错误。调整后组件可独立复用、无运行时问题:
// assets/components/Editor.vue(调整后) <template> <textarea ref="editorTextarea"></textarea> </template> <script> import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor'; import Essentials from '@ckeditor/ckeditor5-essentials/src/essentials'; import Heading from '@ckeditor/ckeditor5-heading/src/heading'; // 保留所有原有的CKEditor插件import export default { name: "Editor", mounted() { // 直接获取组件绑定的DOM节点,补全配置对象的语法结构 ClassicEditor.create(this.$refs.editorTextarea, { plugins: [ Essentials, Heading, // 保留原有的所有插件配置 ], toolbar: [ 'heading', // 保留原有的所有工具栏配置 ], }).then(editor => { // 保留原有的编辑器实例初始化逻辑 }).catch(error => { // 保留原有的错误处理逻辑 }); } } </script>
第三步:新建独立的editor.js入口文件
在assets目录下新建和app.js同级的editor.js,这个文件完全独立于app.js的Vue实例,只负责初始化Editor组件的运行环境,不会和原有全局Vue实例产生冲突:
// assets/editor.js import Vue from 'vue'; import Editor from './components/Editor'; // 找页面上专门为编辑器预留的挂载容器,初始化独立的Vue实例 const editorMountEl = document.getElementById('editor-app'); if (editorMountEl) { new Vue({ render: h => h(Editor) }).$mount('#editor-app'); }
第四步:更新Webpack Encore配置
在根目录的webpack.config.js里新增editor入口的配置,Encore默认开启的公共依赖拆分能力,会自动把Vue这类跨入口的公共代码提取到单独的vendor文件里,不会在app.js和editor.js中重复打包:
// webpack.config.js(调整部分) Encore // 保留原有的app入口配置 .addEntry('app', './assets/app.js') // 新增独立的editor入口 .addEntry('editor', './assets/editor.js') // 保留所有原有的Encore配置(splitEntryChunks、enableVueLoader等默认配置不需要改动)
第五步:页面按需引入脚本
在Twig模板里,仅在有编辑器需求的页面额外引入editor入口对应的脚本,不需要编辑器的页面保持原有脚本引入逻辑即可。Encore会自动处理脚本加载顺序、公共依赖去重的问题,不需要手动写冗余的script标签:
- 普通无编辑器页面:只加载app.js,不会包含任何CKEditor相关代码
{# 普通页面模板 #} {{ encore_entry_script_tags('app') }}
- 需要编辑器的页面:在原有app脚本的基础上,额外引入editor脚本
{# 含编辑器的页面模板 #} {{ encore_entry_script_tags('app') }} {{ encore_entry_script_tags('editor') }} {# 编辑器预留的挂载容器 #} <div id="editor-app"></div>
如果不想在每个需要编辑器的页面手动引editor.js,也可以不用多入口拆分的方式,直接在app.js里用Vue的异步组件语法把Editor注册为全局组件,Webpack会自动把Editor相关的CKEditor代码拆成独立的chunk,只有当页面实际出现<editor>标签时才会自动加载对应代码,同样能达到不增加公共包体积的效果,配置方式为:
// assets/app.js(异步组件注册方式) import Vue from 'vue'; // 异步加载Editor组件,不直接静态import,Webpack会自动完成代码分割 const Editor = () => import('./components/Editor'); new Vue({ el: '#app', components: { Editor } });
内容的提问来源于stack exchange,提问作者Syllz

