Optimizing a Vue.js Internal Ops System: From Tech Stack to Build Strategies
This article details the design and implementation of Tencent Cloud's internal YY‑DSA operations platform, covering project background, frontend technology selection (Vue.js, Element‑UI, webpack), project structure, development environment, build optimizations such as code splitting, CommonsChunk, and the comparison of Dll versus externals for faster builds.
Project Background
The front‑end team built an internal operations system for Tencent Cloud DSA, called YY‑DSA. Because it is internal, the team could freely choose the technology stack but had to follow strict architectural guidelines: clear module responsibilities, low coupling, and maintaining overall efficiency without sacrificing process efficiency for program speed.
Frontend Technology Selection
After evaluating options, the team chose Vue.js as the MV* framework because the team was already familiar with it, reducing learning cost. Vue’s virtual DOM provides good performance, and its API is concise and easy to adopt.
For UI components, several libraries were examined (bootstrap‑vue, uiv, vue‑beauty, element‑ui, iview). The team selected Element‑UI due to its design size, scoped‑slot style, and similarity to Ant Design while fitting the project’s needs.
The build automation tool selected was webpack rather than gulp, because webpack excels at module bundling and offers better performance for the project’s primary need of packaging.
Project Structure
Front‑end structure (generated by vue‑webpack scaffold):
├── build // build tools and dev server
├── config // build configuration
├── dist // compiled output
├── lib-dist // external libraries
├── index.html // entry HTML
├── node_modules
├── src // source code
│ ├── router
│ ├── pages
│ ├── components
│ ├── util
│ ├── style
│ ├── assets
│ ├── App.vue
│ └── main.js
└── package.jsonWeb server structure :
├── middleware
├── node_modules
├── lib
├── util
├── route
├── dao
├── controller
├── app.js
├── config.js
└── package.jsonFront‑end Development Environment
The scaffold provides a dev‑server that can be started with npm run dev. It incorporates three key middleware:
webpack-dev-middleware : compiles assets to memory for fast response.
webpack-hot-middleware : enables hot module replacement via a long‑lived connection.
http-proxy-middleware : proxies API requests to the backend while serving static resources locally.
Proxy configuration uses a zero‑width‑assertion regex to redirect all non‑/api requests to the local dev server, e.g.:
/yy.dsa.oa.com(?!/api)(.*)/i localhost:8080$1Front‑end Build Adjustments
Code Splitting
To avoid a monolithic app.js, the team uses require.ensure to split business pages into separate chunks, loading them on demand.
// router/index.js
let Vue = require('vue');
let Router = require('vue-router');
Vue.use(Router);
const requireUserVip = (component) => {
return (resolve, reject) => {
return require.ensure([], (item) => {
resolve(require('@/pages/user/vip/index.js')[component]);
}, "user-vip");
}
};
module.exports = new Router({
mode: 'history',
routes: [
{path: '/user/vip/list', name: 'user-vip-list', component: requireUserVip("list")},
{path: '/user/vip/add', name: 'user-vip-add', component: requireUserVip("add")},
{path: '/user/vip/edit/:app_id', name: 'user-vip-edit', component: requireUserVip("edit")},
{path: '/user/vip/detail/:app_id', name: 'user-vip-detail', component: requireUserVip("detail")}
]
});Module Format Conversion
Because require.ensure uses CommonJS, the project’s .babelrc was updated with transform-es2015-modules-commonjs. Vue‑loader’s esModule option was set to false in build/vue-loader.conf.js to keep .vue files in CommonJS format.
// build/vue-loader.conf.js
module.exports = {
loaders: loaders,
transformToRequire: {
video: 'src',
source: 'src',
img: 'src',
image: 'xlink:href'
},
esModule: false // disable ES module output for .vue files
};CommonsChunk Optimization
The default webpack config already extracts node_modules into a common chunk. Additional configuration was added to extract shared utility modules and to create a manifest chunk, preventing duplicate inclusion of util code across business chunks.
// Example snippet from build/webpack.prod.conf.js
new webpack.optimize.CommonsChunkPlugin({
name: 'node-modules',
minChunks: function (module) {
return module.resource && /\.js$/.test(module.resource) &&
isInvolve(module.resource, [pathJoin("../node_modules")]);
},
chunks: ['app']
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'common',
minChunks: function (module) {
return module.resource && /\.js$/.test(module.resource) &&
isInvolve(module.resource, [pathJoin("../src/util")]);
},
chunks: ['app']
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
chunks: ['common', 'node-modules']
});Dll vs. Externals
To speed up builds, two strategies were evaluated:
Dll : pre‑bundle stable libraries (Vue, Vue‑router, Vue‑resource, Element‑UI) into a separate DLL bundle using webpack.DllPlugin and reference it with DllReferencePlugin.
Externals : declare these libraries as external globals, load them via script tags, and tell webpack not to bundle them.
Both approaches reduced build time, but externals gave a larger gain because DLL still required copying the bundles into dist. The team ultimately adopted the externals method.
Conclusion
Technology selection should match actual needs, not necessarily be the most cutting‑edge.
Simplicity and overall benefit outweigh premature performance tweaks.
Continuous exploration of small details can yield significant improvements.
Thanks to mentor alsotang for guidance (GitHub: https://github.com/alsotang).
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Tencent IMWeb Frontend Team
IMWeb Frontend Community gathering frontend development enthusiasts. Follow us for refined live courses by top experts, cutting‑edge technical posts, and to sharpen your frontend skills.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
