Vue-cli webpack template project configuration file analysis, vue-cliwebpack
Because a small item is recently written based on the webpack template project generated by vue-cli, some related configurations in build and config need to be changed during the development process, so I just took this opportunity to read all the configuration files and take a look at the logic, which makes it easier to modify the configuration in the future ".
I. File structure
This article mainly analyzes the files involved in the Development (dev) and build processes, so the following file structure only lists the corresponding content.
├─build│ ├─build.js│ ├─check-versions.js│ ├─dev-client.js│ ├─dev-server.js│ ├─utils.js│ ├─vue-loader.conf.js│ ├─webpack.base.conf.js│ ├─webpack.dev.conf.js│ ├─webpack.prod.conf.js│ └─webpack.test.conf.js├─config│ ├─dev.env.js│ ├─index.js│ ├─prod.env.js│ └─test.env.js├─...└─package.json
Ii. Command Analysis
First, check the scripts field in package. json,
"scripts": { "dev": "node build/dev-server.js", "build": "node build/build.js", "unit": "cross-env BABEL_ENV=test karma start test/unit/karma.conf.js --single-run", "e2e": "node test/e2e/runner.js", "test": "npm run unit && npm run e2e", "lint": "eslint --ext .js,.vue src test/unit/specs test/e2e/specs" }
If you do not want to test, you can directly view "dev" and "build ". When running "npm run dev", build/dev-server.js files are executed, while "npm run build" is executed. js file. We can start to read and analyze the code from these two files.
3. build folder Analysis
Build/dev-server.js
First, let's take a look at the build/dev-server.js file that was first executed when "npm run dev" was executed. This file mainly completes the following tasks:
- Check node and npm versions
- Introduce related plug-ins and configurations
- Create an express server and webpack Compiler
- Webpack-dev-middleware and webpack-hot-middleware)
- Mount proxy services and Middleware
- Configure static Resources
- Start the server to listen to a specific port (8080)
- Automatically open the browser and open a specific URL (localhost: 8080)
Note:The express server provides static file services, but it also uses http-proxy-middleware, an http request proxy middleware. If you need to use backend APIs during front-end development, you can configure proxyTable to proxy the corresponding back-end requests to the dedicated API server.
For details, see the code comment:
// Check the NodeJS and npm version require ('. /check-versions ') () // obtain the configuration var config = require ('.. /config') // if the Node environment variable does not set the current environment (NODE_ENV), use the configuration in config as the current environment if (! Process. env. NODE_ENV) {process. env. NODE_ENV = JSON. parse (config. dev. env. NODE_ENV)} // a plug-in that can call the default software to open URLs, images, files, and other content. // use it to call the default browser to open the dev-server listening port, for example: localhost: 8080var opn = require ('stop') var path = require ('path') var express = require ('express ') var webpack = require ('webpackage ') // an express middleware that proxy http requests to other servers // example: localhost: 8080/api/xxx --> localhost: 3000/api/xxx // This plug-in can be used to proxy requests involved in front-end development to the API server, which is convenient The server connects to var proxyMiddleware = require ('HTTP-proxy-middleware ') // introduce the corresponding webpack configuration var webpackConfig = process according to the Node environment. env. NODE_ENV = 'testing '? Require ('. /webpack. prod. conf '): require ('. /webpack. dev. conf ') // dev-server listening port. The default value is config. dev. port: 8080var port = process. env. PORT | config. dev. port // Boolean variable used to determine whether to automatically open the browser. The value of this variable is falsevar autoOpenBrowser = when the browser is not set in the configuration file !! Config. dev. autoOpenBrowser // define the HTTP Proxy table and proxy to the API server var proxyTable = config. dev. proxyTable // create one express instance var app = express () // create the Compiler object var compiler = webpack (webpackConfig) according to the webpack configuration file) // webpack-dev-middleware uses the compiler object to compile and bind the corresponding file. // After compilation and binding, the product is stored in the memory and not written into the disk. // after the middleware is handed over to express, you can access the compiled product file var devMiddleware = require ('webpack-dev-middleware ') (compiler, {publicPath: webpackConfig. out Put. publicPath, quiet: true}) // webpack-hot-middleware, which is used to implement the hot-loaded middleware var hotMiddleware = require ('webpack-hot-middleware ') (compiler, {log: () =>{}}) // After html-webpack-plugin is submitted, the reload action is published using the hot-load middleware to reload compiler on the page. plugin ('compilation', function (compilation) {compilation. plugin ('html-webpack-plugin-after-emit', function (data, cb) {hotMiddleware. publish ({action: 'reload'}) cb ()}) // set the proxy in proxyTable The request configuration is mounted to the Object on the express server. keys (proxyTable ). forEach (function (context) {var options = proxyTable [context] // format options. For example, convert 'www .example.com 'to {target: 'www .example.com '} if (typeof options = 'string') {options = {target: options} app. use (proxyMiddleware (options. filter | context, options)} // handle fallback for HTML5 history API // redirect URLs that do not exist, which are often used in SPAapp. use (require ('connect-history-api-fal Lback ') () // serve webpack bundle output // use webpack to develop middleware // compile the webpack and output it to the file resources in the memory and then mount it to the express server app. use (devMiddleware) // enable hot-reload and state-preserving // compilation error display // mount the hot-load middleware to the express server app. use (hotMiddleware) // serve pure static assets // path of static resources var staticPath = path. posix. join (config. dev. assetsPublicPath, config. dev. assetsSubDirectory) // Mount static resources to the express server app. use (staticPat H, express. static ('. /static ') // application address, for example, http: // localhost: 8080var uri = 'HTTP: // localhost: '+ port // webpack development middleware is valid (valid) and then a prompt is output to the console, indicating that the server has started devMiddleware. waitUntilValid (function () {console. log ('> Listening at' + uri + '\ n')}) // start the express server and listen to the corresponding port (8080) module. exports = app. listen (port, function (err) {if (err) {console. log (err) return} // when env is testing, don't need open it // If When the browser condition is automatically opened, the system will open the corresponding URL uri if (autoOpenBrowser & process. env. NODE_ENV! = 'Testing') {fig (uri )}})
Build/webpack. base. conf. js
The Code shows that the webpack configuration used by dev-server comes from build/webpack. dev. conf. js files (build/webpack is used in the test environment. prod. conf. js, the test environment is not considered here ). Webpack. base. conf. js is referenced in build/webpack. dev. conf. js, so here I will analyze webpack. base. conf. js first.
Webpack. base. conf. js mainly completes the following tasks:
- Webpack compilation entry
- Configure the webpack output path and naming rules
- Configure the resolve rules of the module
- Configure processing rules for different types of modules
Note:This configuration only configures processing rules for. js,. vue, images, fonts, and other types of files. If you need to process other files, you can configure them in module. rules.
For details, see the code comment:
Var path = require ('path') var utils = require ('. /utils ') var config = require ('.. /config') var vueLoaderConfig = require ('. /vue-loader.conf ') // returns the correct absolute path function resolve (dir) {return path. join (_ dirname ,'.. ', dir)} module. exports = {// configure the webpack compilation entry: {app :'. /src/main. js '}, // configure the webpack output path and the naming rule output: {// the path of the target folder output by webpack (for example,/dist) path: config. build. assetsRoot, // webpack output bundle file name Filename: '[name]. js', // publish path of webpack compilation and output: publicPath: process. env. NODE_ENV = 'production '? Config. build. assetsPublicPath: config. dev. assetsPublicPath}, // configure the resolve rule of the module resolve: {// auto resolve extension extensions :['. js ','. vue ','. json'], // The modules folder to be searched when the resolve module is used: [resolve ('src'), resolve ('node _ modules ')], // create a path alias, it is more convenient to reference a module with an alias, for example, // import Vue from 'vue/dist/vue. common. js' can be written as import Vue from 'vue 'Alias: {'vue $ ': 'vue/dist/vue. common. js', 'src': resolve ('src'), 'assets': res Olve ('src/assets'), 'components': resolve ('src/components') }}, // configure the processing rule module for different types of modules: {rules: [{//. js and. use eslint-loader test:/\ In the vue file :/\. (js | vue) $/, loader: 'eslint-loader ', enforce: "pre", include: [resolve ('src'), resolve ('test')], options: {formatter: require ('eslint-friendly-formatter ') }}, {// All. the vue file uses vue-loader test :/\. vue $/, loader: 'vue-loader ', options: vueLoaderCon Fig}, {// under the src and test folders. use babel-loader test :/\. js $/, loader: 'babel-loader ', include: [resolve ('src'), resolve ('test')]}, {// use url-loader and query for image resource files. name indicates the output naming rule test :/\. (png | jpe? G | gif | svg )(\?. *)? $/, Loader: 'url-loader ', query: {limit: 10000, name: utils. assetsPath ('img/[name]. [hash: 7]. [ext] ') }},{ // use url-loader and query for font resource files. name indicates the output naming rule test :/\. (woff2? | Eot | ttf | otf )(\?. *)? $/, Loader: 'url-loader ', query: {limit: 10000, name: utils. assetsPath ('fonts/[name]. [hash: 7]. [ext] ') }}}
Build/webpack. dev. conf. js
Next, let's take a look at webpack. dev. conf. js. Here we have added and improved the configuration in the development environment based on webpack. base. conf, including the following:
- Add the Code related to hot-reload to entry chunks.
- Merge basic webpack configurations
- Use styleLoaders
- Configure Source Maps
- Configure the webpack plugin
For details, see the code comment:
Var utils = require ('. /utils ') var webpack = require ('webpackage') var config = require ('.. /config') // a plug-in var merge = require ('webpack-merge') var baseWebpackConfig = require ('. /webpack. base. conf ') // A webpack plug-in var HtmlWebpackPlugin = require ('html-webpack-plugin') used to generate HTML files and automatically inject dependent files (link/script ') // outputs webpack warning and error information more efficiently. var FriendlyErrorsPlugin = require ('dldly-errors-webpack-In in ')// Add hot-reload related code to entry chunksObject. keys (baseWebpackConfig. entry ). forEach (function (name) {baseWebpackConfig. entry [name] = ['. /build/dev-client ']. concat (baseWebpackConfig. entry [name])} // merge the basic webpack configuration module. exports = merge (baseWebpackConfig, {// configure the processing rules of the style file, and use styleLoaders module: {rules: utils. styleLoaders ({sourceMap: config.dev.css SourceMap})}, // configure Source Maps. Use cheap-module-eval-source-map in development for faster devtool: '# cheap-module-eval-source-map', // configure the webpack plug-in plugins: [new webpack. definePlugin ({'process. env': config. dev. env}), // https://github.com/glenjamin/webpack-hot-middleware#installation--usage new webpack. hotModuleReplacementPlugin (), // After the page, the error will not be blocked, but new webpack will be reported after compilation. noEmitOnErrorsPlugin (), // https://github.com/ampedandwired/html-webpack-plugin new HtmlWebpackPlugin ({filename: 'index.html ', template: 'index.html', inject: true}), new FriendlyErrorsPlugin ()]})
Build/utils. js and build/vue-loader.conf.js
The previous webpack configuration file used utils. js and vue-loader.conf.js these two files, utils mainly complete the following three things:
- Configure static resource path
- Generate cssLoaders for loading styles in the. vue File
- Generate styleLoaders to load a unique style file that does not exist in the. vue file.
The vue-loader.conf only configures the css loader and automatically adds the prefix after the css is compiled. For details, please see the code comment (below is the vue-loader.conf code, utils code in the original notes have corresponding instructions here will not post out ):
Var utils = require ('. /utils ') var config = require ('.. /config') var isProduction = process. env. NODE_ENV = 'production 'module. exports = {// css loader loaders: utils.css Loaders ({sourceMap: isProduction? Config. build. productionSourceMap: config.dev.css SourceMap, extract: isProduction}), // After css compilation, the prefix postcss is automatically added: [require ('autoprefixer') ({browsers: ['last 2 version']})]}
Build/build. js
After completing the configuration in the development environment, let's look at the configuration in the build environment. When "npm run build" is executed, the build/build. js file is first executed. build. js mainly completes the following tasks:
- Loading Animation
- Delete the target folder
- Webpack Compilation
- Output Information
Note:After the webpack is compiled, it is output to the specified target folder in the configuration. After the target folder is deleted, it is created to remove the old content, so as to avoid unpredictable impact.
For details, see the code comment:
// The https://github.com/shelljs/shelljs// checks the NodeJS and npm version require ('. /check-versions ') () process. env. NODE_ENV = 'production '// Elegant terminal spinnervar ora = require ('ora') var path = require ('path ') // outputs the color-based plug-in var chalk = require ('chalk ') on the console // execute the Unix Command Line plug-in var shell = require ('shelljs ') var webpack = require ('webpackage') var config = require ('.. /config') var webpackConfig = require ('. /webpack. prod. conf ') var spinner = ora ('Building for production... ') spinner. start () // enable loading animation // var assetsPath = path in the target folder of the output file. join (config. build. assetsRoot, config. build. assetsSubDirectory) // recursively Delete the old target folder shell. rm ('-rf', assetsPath) // recreate the shell folder. mkdir ('-p', assetsPath) shell. config. silent = true // copy the static folder to the output target folder shell. cp ('-R', 'static/*', assetsPath) shell. config. silent = false // compile webpack (webpackConfig, function (err, stats) {spinner. stop () // stop loading animation if (err) throw err // if no error occurs, the relevant information process is output. stdout. write (stats. toString ({colors: true, modules: false, children: false, chunks: false, chunkModules: false}) + '\ n \ n') console. log (chalk. cyan ('build complete. \ n') console. log (chalk. yellow ('tip: built files are meant to be served over an HTTP server. \ n' + 'opening index.html over file: // won \'t work. \ n '))})
Build/webpack. prod. conf. js
The webpack configuration used during construction comes from webpack. prod. conf. js. This configuration is also further improved based on webpack. base. conf. This mainly completes the following tasks:
- Merge basic webpack configurations
- Use styleLoaders
- Configure webpack output
- Configure the webpack plugin
- Webpack plug-in configuration in gzip Mode
- Webpack-bundle Analysis
Note:The webpack plug-in contains many plug-ins, such as the ugly compression code and the extraction of css files.
For details, see the code:
Var path = require ('path') var utils = require ('. /utils ') var webpack = require ('webpackage') var config = require ('.. /config') var merge = require ('webpack-merge') var baseWebpackConfig = require ('. /webpack. base. conf ') var HtmlWebpackPlugin = require ('html-webpack-plugin') // The plug-in used to extract text from the bundle generated by webpack to a specific file. // css can be extracted, the js file separates it from the bundle output by webpack. var ExtractTextPlugin = require ('extract-text-webpack-plugin') v Ar env = process. env. NODE_ENV = 'testing '? Require ('.. /config/test. env '): config. build. env // merge the basic webpack configuration var webpackConfig = merge (baseWebpackConfig, {module: {rules: utils. styleLoaders ({sourceMap: config. build. productionSourceMap, extract: true})}, devtool: config. build. productionSourceMap? '# Source-map': false, // configure the webpack output: {// compile the output directory path: config. build. assetsRoot, // compile the output file name format filename: utils. assetsPath ('js/[name]. [chunkhash]. js'), // the file name format chunkFilename: utils. assetsPath ('js/[id]. [chunkhash]. js ')}, // configure the webpack plugin plugins: [// http://vuejs.github.io/vue-loader/en/workflow/production.html new webpack. definePlugin ({'process. env ': env}), // ugly Compression Code new web Pack. optimize. uglifyJsPlugin ({compress: {warnings: false}, sourceMap: true}), // extract the css file new ExtractTextPlugin ({filename: utils. assetsPath ('css/[name).w.contenthash).css ')}), // generate dist index.html with correct asset hash for caching. // you can customize output by editing/index.html // see https://github.com/ampedandwired/html-webpack-plugin new HtmlWebpackPlugin ({filename: process. en V. NODE_ENV = 'testing '? 'Index.html ': 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 '}), // split vendor js into its own file new webpack. optimize. commonsChunkPlugin ({name: 'vendor', minChunks: function (module, count) {// any required modules inside node_modules are extracted to vendor return (module. resource & amp &&/\. js $ /. test (module. resource) & module. resource. indexOf (path. join (_ dirname ,'.. /node_modules ') = 0 )}}), // extract webpack runtime and module manifest to its own file in order to // prevent vendor hash from being updated whenever app bundle is updated new webpack. optimize. commonsChunkPlugin ({name: 'manifest ', chunks: ['vendor']}) // compression plug-in needs to be introduced in gzip mode for compression if (config. build. productionGzip) {var CompressionWebpackPlugin = require ('Compression-webpack-plugin') webpackConfig. plugins. push (new CompressionWebpackPlugin ({asset: '{path}.gz [query] ', algorithm: 'gzip', test: new RegExp ('\\. ('+ config. build. productionGzipExtensions. join ('|') + ') $'), threshold: 10240, minRatio: 0.8})} if (config. build. bundleAnalyzerReport) {var BundleAnalyzerPlugin = require ('webpack-bundle-analyzer '). bundleAnalyzerPlugin webpackConfig. plugins. push (new BundleAnalyzerPlugin ()} module. exports = webpackConfig
Build/check-versions.js & build/dev-client.js
Finally, the build folder below two relatively simple files, dev-client.js does not seem to be used, the code is relatively simple, here not to mention. The check-version.js completes Version Detection for node and npm, and the following is its code comment:
// Used to output The var chalk = require ('chalk ') Plug-in with a color font on The console // The semantic version parser used by npm) var semver = require ('secret') // introduce package. jsonvar packageConfig = require ('.. /package. json') // open the sub-process to execute command cmd and return the result function exec (cmd) {return require('child_process'cmd.exe cSync (cmd ). toString (). trim ()} // node and npm version requirements var versionRequirements = [{name: 'node', currentVersion: semver. clean (process. versio N), versionRequirement: packageConfig. engines. node}, {name: 'npm ', currentVersion: exec ('npm -- version'), versionRequirement: packageConfig. engines. npm}] module. exports = function () {var warnings = [] // judge whether the version meets the requirements in sequence for (var I = 0; I <versionRequirements. length; I ++) {var mod = versionRequirements [I] if (! Semver. satisfies (mod. currentVersion, mod. versionRequirement) {warnings. push (mod. name + ':' + chalk. red (mod. currentVersion) + 'should be '+ chalk. green (mod. versionRequirement) }}// if there is a warning, output it to the console if (warnings. length) {console. log ('') console. log (chalk. yellow ('To use this template, you must update following to modules:') console. log () for (var I = 0; I <warnings. length; I ++) {var warning = warnings [I] console. log (''+ warning)} console. log () process. exit (1 )}}
Iv. config folder Analysis
Config/index. js
The main file in the config folder is index. js. The configuration in the development and build environments is described here. Many files in the previous build folder also reference the index. configuration in js. Below is a code comment:
// See http://vuejs-templates.github.io/webpack for documentation. var path = require ('path') module. exports = {// The configuration build: {// The compiling environment env: require ('. /prod. env'), // compile the index.html file index: path. resolve (_ dirname ,'.. /dist/index.html '), // path of the target folder output by webpack: assetsRoot: path. resolve (_ dirname ,'.. /dist '), // assetsSubDirectory: 'static', // assetsPublicPath: '/' of the second-level folder for webpack compilation and output, // use SourceMap productionSourceMap: true, // Gzip off by default as your popular static hosts such as // Surge or Netlify already gzip all static assets for you. // Before setting to 'true', make sure to: // npm install -- save-dev compression-webpack-plugin // by default, gzip mode productionGzip is disabled: false, // productionGzipExtensions: ['js', 'css '], // Run the build command with an extra argument to // View the bundle analyzer report after build finishes: // 'npm run build -- report' // Set to 'true' or 'false' to always turn it on or off bundleAnalyzerReport: process. env. npm_config_report}, // configuration used during development dev: {// The compiling environment of webpack env: require ('. /dev. env '), // dev-server listening port: 8080, // After dev-server is started, the browser autoOpenBrowser: true is automatically opened, // assetsSubDirectory is the second-level folder for webpack compilation and output: 'static ', // publish path of webpack compilation and output assetsPublicPath:'/', // request proxy table, here, you can configure a specific request proxy to the corresponding API interface // For example, proxy '/api/XXX' to 'www .example.com/api/xxx' proxyTable :{}, // CSS Sourcemaps off by default because relative paths are "buggy" // with this option, according to the CSS-Loader README /( https://github.com/webpack/css-loader#sourcemaps) // In our experience, they generally work as expected, // just be aware of this issue when enabling this option. // whether to enable cssSourceMap: false }}
Config/dev. env. js, config/prod. env. js, and config/test. env. js
These three files simply set the environment variables, nothing special.
V. Summary
Here, we have a basic understanding of the content in the build and config folders of the template project, and know where to modify the configuration according to your needs in actual use. For example, when I need to configure the proxy. dev. proxyTable settings, When I modify the resource folder name static, also need to be in config/index. set in js. The general feeling is that webpack is getting started, but it is not really understandable. There are many webpack plug-ins. If you encounter plug-ins that you don't know during code reading, you need to view many documents (github, npm, or blog ), in the actual process, changing the plug-in configuration or using the new plug-in also requires the introduction of the document and other online blogs.
The above is all the content of this article. I hope this article will help you in your study or work. I also hope to provide more support to the customer's home!