The second article in the Vuejs Undoing series builds on a solid foundation of Vuejs and Webpack, using vuE-CLI scaffolding to quickly build a project. This article goes through the file configuration and usage of the project.

Tips: This article mainly sorts out the configuration under vuE-CLI scaffolding rapid construction project, and basically Outlines the key configuration codes of all files. The following is the sorting done by the author in my spare time. It is very hard, and I hope friends can give the warehouse address ★(star) :

“Https://github.com/WeideMo/vuecli-webpack-configs”

In addition, if in the process of using VUE development, there are some puzzling problems, you can also refer to my previous article Vuejs Series 1: Daily development must master the details (KENG), I believe you will also have a lot of harvest.

To prepare

Installing the COMMAND Line Tool (CLI)

Vue.js provides a user-friendly command line tool. After global dependencies are installed, it is easy to create and start a project with scaffolding anywhere in the file system, equipped with thermal overloads, statically checked at save time, and build configurations that can be used in production.

$NPM install --global vue-cli # create a new project based on webpack template $vue init webpack my-project my-project $ npm install $ npm run devCopy the code

Viewing installation Results

Vue -v 2.8.1Copy the code

The project of

The directory structure

├ ─ ─ 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. Test. Conf., js │ └ ─ ─ Webpack. Prod. Conf. Js ├ ─ ─ the config │ ├ ─ ─. Dev env. Js │ ├ ─ ─ index. The js │ ├ ─ ─ test. The env. Js │ └ ─ ─ the prod. The env. Js ├ ─ ─ node_modules ├ ─ ─ The SRC │ ├ ─ ─ App. Vue │ ├ ─ ─ assets │ │ └ ─ ─ img. PNG │ ├ ─ ─ components │ │ └ ─ ─ hello.html vue │ └ ─ ─ main. Js ├ ─ ─ the static ├ ─ ─ the test │ └ ─ ─ unit │ │ ├ ─ ─ ─ coverage │ │ ├ ─ ─ ─ specs │ │ ├ ─ ─ ─ the eslintrc │ │ ├ ─ ─ ─ index. The js │ │ └ ─ ─ karma. Conf., js │ └ ─ ─ e2e ├ ─ ─ .├ ──.├.html ├─ Package.json ├.mdCopy the code

/build

build.js

During the execution of NPM run build, the JS script is mainly to load the Webpack configuration in the production environment, and rebuild the compression project used in the production environment according to the Webpack configuration. Finally, the resource file will be generated into the dist file in the root directory.

check-version.js

A check step prior to build as a check before building the production project package.

dev-client.js

require('eventsource-polyfill') var hotClient = require('webpack-hot-middleware/client? noInfo=true&reload=true') hotClient.subscribe(function (event) { if (event.action === 'reload') { window.location.reload() } })Copy the code

The hot reload plugin is loaded and the page is reloaded when the action of the listening event changes to Reload.

dev-server.js

var app = express(); . var hotMiddleware = require('webpack-hot-middleware')(compiler, { log: false, heartbeat: 2000 })Copy the code

Express is used to implement a locally developed service, and the hot reload function is configured to cooperate with the local development browser side automatic reload.

utils.js

Utils.js is a utility method that provides static asset paths to the response webpack configuration:

exports.assetsPath = function (_path) {
  var assetsSubDirectory = process.env.NODE_ENV === 'production'
    ? config.build.assetsSubDirectory
    : config.dev.assetsSubDirectory
  return path.posix.join(assetsSubDirectory, _path)
}
Copy the code

Provides various configuration of loaders, such as cssLoaders, CSS/postcss/less sass/SCSS/stylus/styl after pretreatment or processor configuration such as:

  return {
    css: generateLoaders(),
    postcss: generateLoaders(),
    less: generateLoaders('less'),
    sass: generateLoaders('sass', { indentedSyntax: true }),
    scss: generateLoaders('sass'),
    stylus: generateLoaders('stylus'),
    styl: generateLoaders('stylus')
}
Copy the code

vue-loader.conf.js

As the name implies, this file is the configuration for vUE single file, mainly some single file using CSS preprocessing configuration, as well as some file resources conversion configuration items.

webpack.base.conf.js

The generic webPack configuration file, the webPack configuration that needs to be loaded regardless of whether the environment is Test, Develop, or Production, is important and often requires configuration changes:

Entry file entry

entry: {
  app: './src/main.js',
  utils:['./src/assets/libs/jquery.js']
}
Copy the code

By default, there is only main.js for app and utils for custom entry. By configuring multiple file entry, the file size after build can be reduced, and project subcontracting can also be carried out with CommonsChunkPlugin.

Output file output

The config configuration is in the config/index.js file

Output: {path: config.build.assetsRoot, // absolute path of the export directory filename: '[name].js', // filename of the export file publicPath: process.env.NODE_ENV === 'production'? Config. Build. AssetsPublicPath: config. Dev. AssetsPublicPath / / production mode or development mode of HTML, js file such as the internal reference public path}Copy the code

File resolve

It mainly sets how modules are parsed.

Resolve: {extensions: ['.js', '.vue', '.json'], // Resolve: {extensions: ['.js', '.vue', '.json'], // {// Alias 'vue$': 'vue/dist/vue.esm.js', '@': resolve(' SRC ')}}Copy the code

By default, vue$is the alias of the vue.esm.js file, @ is the alias of the/SRC directory, @/ XXX. SCSS or LESS files are not allowed to use @ to find files.

Module resolution mechanism Module

This module is mainly used to define files with different file suffixes, which loaders should be used for load parsing. Different from Webpack 1.x, the original loaders are replaced by rules. Vue,.js,img class, media class, font class, etc. The default vue-CLI is already equipped with file parsing for.vue,.js,img class, media class, font class, etc. Meanwhile, if the.vue component needs to use the pre-processing language, you need to add lang attribute to the

<style lang="scss" scoped>
        body{
          background-color:#FFF;
        }
</style>
Copy the code

webpack.dev.conf.js

Merge the basic configuration of webpack.base.conf.js using the merge method

var merge = require('webpack-merge')
var baseWebpackConfig = require('./webpack.base.conf')
module.exports = merge(baseWebpackConfig, {})
Copy the code

The module configuration

Module: {// Get the rules configuration by passing in some configuration. SourceMap: false does not generate sourceMap rules: utils.styleLoaders({sourceMap: config.dev.cssSourceMap }) }Copy the code

Here is a reference to the styleLoaders method in utils.js, which automatically generates the following configuration

Exports.styleloaders = function (options) {var output = [] // call cssLoaders to return each type of style object (CSS: Var loaders = exports.cssloaders (options) {var loaders = exports.cssloaders (options) { Var loader = loaders[extension] output.push({// Use the regex match to determine the type of style file. Loaders test: new RegExp('\\.' + extension + '$'), use: loader})} return output}Copy the code

The above code calls exports.cssloaders (options), which is used to preprocess various CSS loaders

exports.cssLoaders = function (options) { options = options || {} var cssLoader = { loader: 'css-loader', options: NODE_ENV === 'production', // Generate sourceMap file sourceMap: options.sourceMap } } function generateLoaders (loader, LoaderOptions) {// Preset csS-loader var loaders = [cssLoader] Loaders. Push ({loader: loader + '-loader', options: object. assign({}, loaderOptions, {sourceMap: loaders + '-loader', options: object. assign({}, loaderOptions, {sourceMap: Options.sourcemap})})} // If the options passed in exist extract and are true if (options.extract) {// Separate the CSS files imported in JS by using the ExtractTextPlugin Return ExtractTextPlugin. Extract ({use: loaders, / / not used by the extraction and separation of vue - style - loader loads fallback: 'vue-style-loader'})} else {// If no options are passed to extract or false, Use vue-style-loader to process return ['vue-style-loader']. Concat (loaders)}} return {// Return objects of loaders corresponding to the CSS type GenerateLoaders () : generateLoaders(), postCSS: generateLoaders(), less: generateLoaders('less'), sass: generateLoaders('sass', { indentedSyntax: true }), scss: generateLoaders('sass'), stylus: generateLoaders('stylus'), styl: generateLoaders('stylus') } }Copy the code

The plug-in configuration

Plugins: [// new webpack.defineplugin ({// the current environment is the development environment 'process.env': Config. Dev. Env}), / / hot reload plug-ins new webpack HotModuleReplacementPlugin (), / / do not trigger the error, which is compiled package normal operation of the new webpack. NoEmitOnErrorPlugin (), / / to automatically generate HTML file new HtmlWebpackPlugin ({filename: 'index.html', // Generate filename template: 'index.html', // inject: true}), // Friendly error prompt new FriendlyErrorsPlugin()]Copy the code

webpack.prod.conf.js

This file is the configuration file used for packaging the production environment. This file also merges the basic configuration to form the configuration for production:

To determine the environment

Var env = process.env.node_env === 'testing'? require('.. /config/test.env') : config.build.envCopy the code

Load style handler

Module: {// Use the same methods as utils.styleLoaders({sourceMap:). Config. Build. ProductionSourceMap, extract: true})}, / / configuration values by judgment, determine whether production source - the map devtool: config.build.productionSourceMap ? '#source-map' : false }Copy the code

The output file

Output: {// Production resource path: Config. Build. AssetsRoot, / / the generated file name, will typically generate entry name. [hash]. Js, such as app. 7 d0bcfcc47ab773ebe20834b27a0927a. Js filename: Utils. AssetsPath ('js/[name].[chunkhash].js'), // Generates an asynchronous file block, usually assigning id.[hash].js, Such as 0. App. 7 d0bcfcc47ab773ebe20834b27a0927a. Js chunkFilename: utils. AssetsPath (' js / [id]. [chunkhash] js')}Copy the code

Note that the system will automatically generate the asynchronous file block according to the asynchronous component introduced in the router index.js, so we do not need to rename this part of the file, otherwise it is easy to cause the file index error, 404 error.

The plug-in

// Define the global environment to produce new webpack.defineplugin ({'process.env': Env}), / / js compressed plug-in new webpack. Optimize the UglifyJsPlugin ({compress: {/ / don't show the warning warnings: false}, / / production source - the map sourceMap: True}), // New ExtractTextPlugin({// Generated file name, general generated entry name. Such as app. 7 d0bcfcc47ab773ebe20834b27a0927a. CSS filename: Utils.assetspath (' CSS /[name].[contenthash].css')}), // CSS configuration plug-in, New OptimizeCSSPlugin({cssProcessorOptions: {safe: True}}), / / CommonsChunkPlugin public block to extract the plug-in new webpack.optimize.Com monsChunkPlugin ({/ / configuration generated file name: vendor name: 'vendor', minChunks: Function (module, count) {function (module, count) { Return (// regular matches module.resource && /\.js$/.test(module.resource) && module.resource. IndexOf ( path.join(__dirname, '.. /node_modules') ) === 0 ) } }),Copy the code

Note that vue, vuex and other package files are unified in the JS named :vendor via CommonsChunkPlugin. Finally generates a similar call vendor. 7 d0bcfcc47ab773ebe20834b27a0927a. Js, and, of course, in order to prevent the app hash packaging every time change, lead to cannot cache resources, we need to add a manifest, To compile the runtime code separately into the manifest file so that vendor.js’s hash changes with each compilation:

new webpack.optimize.CommonsChunkPlugin({
    name: 'manifest',
    chunks: ['vendor']
  }),
Copy the code

We can also use CommonsChunkPlugin to do this if we need to package the third library js as a separate file called utils.js:

new webpack.optimize.CommonsChunkPlugin({
   names: ["utils"]
 })
Copy the code

Don’t forget that we need to add the manifest processing to it, just make a simple change from what we already have:

new webpack.optimize.CommonsChunkPlugin({
    name: 'manifest',
    chunks: ['vendor','utils']
  }),
Copy the code

Of course, we need to add an entry file to it,

Entry: {app: '. / SRC/main. Js', utils: ['. / SRC/assets/libs/jquery. Js'] / / here you can increase the other three sides according to the requirements of your library file}Copy the code

Other plug-ins

In addition, there are other plug-ins, such as compression-webpack-plugin, for compression based on regular matches; Webpack-bundle-analyzer can optimize the size of your package and so on.

/config

Environment variable Definition

This section defines global environment variables for production, development, and testing to adjust the use of different Webpack configurations in different environments by defining the NODE_ENV variable:

var merge = require('webpack-merge')
var prodEnv = require('./prod.env')

module.exports = merge(prodEnv, {
  NODE_ENV: '"development"'
})
Copy the code

/node_modules

Third package of NPM installation

Here is estimated to have used NPM students are familiar, here is the third party tool class we install through NPM install, we can quickly introduce through the require keyword.

/test

unit

This file is mainly equipped with unit-test for vuE-CLI built projects, which allows users to quickly write component-level unit tests, and to unit test the code by using the NPM run unit command in the root directory:

index.js

const testsContext = require.context('./specs', true, /\.spec$/)
testsContext.keys().forEach(testsContext)
Copy the code

Do.vue unit tests by requiring the use case files in specs in the current directory

const srcContext = require.context('.. /.. /src', true, /^\.\/(? ! main(\.js)? $)/) srcContext.keys().forEach(srcContext)Copy the code

Here we define the source file directory to read. The first line reads the file in a regular way. /.. / SRC to unit test files other than main.js. If we only need to unit test partial files, we can narrow the path down to such as unit test only components under SRC:

const srcContext = require.context('.. /.. /src/components', true, /^\.\/(? ! main(\.js)? $) /)Copy the code

karma.conf.js

Since vuE-CLI is equipped with unit tests using karma. Js, we only need to use the default configuration, generally do not change.

specs

Here is the assertion part of the test case. We write *.spec.js to assert the logical part of the component to achieve the effect of unit test. Here is an example of component instantiation and assert the view text of the component:

import Vue from 'vue'
import Hello from '@/components/Hello'

describe('Hello.vue', () => {
  it('should render correct contents', () => {
    const Constructor = Vue.extend(Hello)
    const vm = new Constructor().$mount()
    expect(vm.$el.querySelector('.hello h1').textContent)
      .to.equal('Welcome to Your Vue.js App')
  })
})
Copy the code

coverage

The unit tests on Karma also provide coverage Rate, which describes whether your unit tests are complete by file, from the number of lines to the number of functions. Check coverage\lcov-report\index.html to see the coverage results:

The root directory

.babelrc

{
  "presets": [
    ["env", {
      "modules": false,
      "targets": {
        "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
      }
    }],
    "stage-2"
  ],
  "plugins": ["transform-runtime"],
  "env": {
    "test": {
      "presets": ["env", "stage-2"],
      "plugins": ["istanbul"]
    }
  }
}
Copy the code

The configuration of Babel is formulated, defining the plug-in to load and the plug-in Istanbul required for the test run

.editorconfig

root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
Copy the code

Edit formats are defined: utF-8 encoding, space indentation, two characters of line indentation and new line insertion at the end, and whitespace at the beginning and end of characters.

.gitignore

The familiar configuration of ignoring committed files during git repository synchronization can be done in an accurate and regular manner without going into details.

.postcssrc.js

The new version of Webpack, whenever equipped with postCSS loaders, will check the root directory to see if it has the configuration file. By exporting plugins, you can configure what you need. Here is my configuration using Autoprefixer and PostCSs-Sprites

module.exports = { "plugins": { // to edit target browsers: use "browserslist" field in package.json "autoprefixer": {}, "postcss-sprites":{ // stylesheetPath: './css', spritePath: './css/images/', filterBy: function(image) { // Allow only png files if (! /\.png$/.test(image.url)) { return Promise.reject(); } return Promise.resolve(); }}}}Copy the code

index.html

<! DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>uvoice</title> </head> <body> <section class="container" id="J_container"> </section> <! -- built files will be auto injected --> </body> </html>Copy the code

HTML template, which can be used by the htmlPlugins plug-in, and the compiled script is automatically injected into the comment line.

package.json

For those of you who have used NPM, this file is used to record and manage the dependencies and version numbers of NPM packages.

README.md

The file, as its name suggests, is a reading guide where you can describe some of the uses or command lines of the project for your records.

conclusion

The bat is a bit long, estimates that can see the classmates here is not much, but is really the author cultivated down every word, estimated must read through the full text of the classmates of vue – cli scaffolding to generate a new understanding of the project, at the same time also can have and study for the first time I feel, is the ingenious projects too much, you really understand, You will suddenly feel the gap between yourself and the design of the project architecture. Of course, this article just read through the configuration of VUE-CLI. In the next article, I will come to some dry things and really go through the whole vue-CLI project.