Now that AngularJS is out in 4.x, my knowledge of it is still in 1.x. I used it to write out web mobile weather app (get out of my university courses out of ()) with ionic. And then I didn’t go any further because it was too difficult. I’m currently working for a company that has a project to make a hybrid mobile app using AngularJS+ Ionic and the 1.x version. I had nothing to do. I’ve been using Vuejs all this time. Then they realized that the project was loading too slowly and asked me if THERE was a way to optimize it. I looked at the engineering structure of the project and found that it was a project packaged with GULP. Maybe I did not grasp the key points well at the beginning of this project, which led to the bloated whole project. I will not use gulp anymore. Since I have been using Vuejs, the template provided by the official CLI is packaged with Webpack, and I used Webpack to write ReactJS before. Therefore, I used WebPack to refactor the project. (• ̀ω•́)✧ is to help those who may experience the same problem. In addition, this article can be used as an introduction to WebPack.

First, configure the project files.

Let me list the configuration in my package.json:

{
  "name": "angular-ionic-webpack"."version": "1.0.0"."description": "a project base on angular 1.x and webpack"."main": "index.js"."scripts": {
    "build": "webpack --config ./build/webpack.prod.config.js"."dev": "set NODE_ENV=dev&& webpack-dev-server --config ./build/webpack.dev.config.js"
  },
  "devDependencies": {
    "css-loader": "^ 0.26.4"."extract-text-webpack-plugin": "^ 3.0.1." "."html-loader": "^ 0.4.4"."html-webpack-plugin": "^ 2.24.1"."style-loader": "^ 0.13.1." "."url-loader": "^ 0.5.7"."webpack": "^ 3.1.0"."webpack-dev-server": "^ 2.9.2." "."webpack-manifest-plugin": "^ 1.3.2." "."webpack-merge": "^ 4.1.0." "
  },
  "dependencies": {
    "angular": "1.4.3"."angular-cache": "^ 4.5.0." "."angular-cookies": "1.4.12"."angular-ui-router": "^" 0.3.2."jquery": "^ 3.2.1." "
  },
  "author": "homer"."license": "MIT"
}Copy the code

In addition, you need to add dependencies to your project.

 "dependencies": {
    "angular": "1.4.3"."angular-cache": "^ 4.5.0." "."angular-cookies": "1.4.12"."angular-ui-router": "^" 0.3.2."jquery": "^ 3.2.1." "
  }Copy the code

Both angular and Angular-cookies are using version numbers (1.4.3 instead of ^), because these versions will clash with angular-UI-Router in the Ionic and cause rendering failures. I also didn’t install ionic here, because I can’t resolve ‘ionic’ error when QUOTING directly. I don’t know why, so I directly called ionic. Bundle. Please have found the reason of the friend trouble to tell me why.

Here are the dependencies used in development:

"devDependencies": {
    "css-loader": "^ 0.26.4"."extract-text-webpack-plugin": "^ 3.0.1." "."html-loader": "^ 0.4.4"."html-webpack-plugin": "^ 2.24.1"."style-loader": "^ 0.13.1." "."url-loader": "^ 0.5.7"."webpack": "^ 3.1.0"."webpack-dev-server": "^ 2.9.2." "."webpack-manifest-plugin": "^ 1.3.2." "."webpack-merge": "^ 4.1.0." "
  },Copy the code

Various loaders are necessary because WebPack converts the non-JS files in your project and packs them together at packaging time. We commonly use csS-loader and URL-loader, which parse CSS and images respectively. For example, we use htMl-loader to parse HTML because it is an Angular 1.x project and there are a lot of HTML templates. The second is Webpack – as an aside, webpack is usually up to date because the packaged environment and the framework used don’t really interfere with each other too much. I initially thought about using the 1.x WebPack and found it inconvenient to use, so I switched back to the latest 3.x. This is also a small personal experience. Then we also used webpack-dev-server. This is the server that we used during development to hot replace the updated code. It’s very convenient. I’ll talk more about how to use it later. Then there is webpack-merge, which is used to merge webpack configuration. This is seen in the Vue project, it feels very good, so I also use it. Finally, there are plugins: extract-text-webpack-plugin, a plugin that packs CSS styles into a single CSS file. Without it, styles would only be injected into index.html as inline styles. Html-webpack-plugin is used to inject JS into index.html; The webpack-manifest-plugin is used to generate the manifest file for a web page. Then write the command line that starts Webpack, which is the one above:

"scripts": {
    "build": "webpack --config ./build/webpack.prod.config.js"."dev": "set NODE_ENV=dev&& webpack-dev-server --config ./build/webpack.dev.config.js"
  },Copy the code

This means that when you type NPM run + the name of your command, NPM will execute your command. Such as input NPM run dev, equivalent to the corresponding set you performed above the dev NODE_ENV = dev && webpack dev – server — config. / build/webpack. Dev. Config. Js “this statement. In this case, the dev command executes the development package and builds the development server; The build command performs production version packaging. At the time of packaging development version, using webpack – dev – server, we let it in. / build/webpack. Dev. Config. The configuration in the js (below) to perform. Webpack run directly in packaging production environment, it is, let it in. / build/webpack. Prod. Config. The configuration in the js to execute.

If you have questions about any other configuration in package.json, please feel free to comment in the comments

Then write the webPack configuration file

An overview of the

With WebPack installed, we need to configure it to work as we expect. The webPack configuration file is usually named webpack.config.js to avoid confusion with other configuration files. However, since we tend to separate development and production environments, packaging requirements for these two environments are a little different. For the development environment, we want it to mimic the production environment directly and put it on the server for testing; Then I thought that it would automatically package the update and display it on the page as soon as it changed, without us having to manually refresh the browser. I don’t want it to take too long to pack; If something goes wrong there will be a corresponding prompt and so on. In production we want to minimize file size, generate manifest files and so on. Therefore, we need to separate the configuration of the development package from the production package. Here we separate the webpack.dev.config.js and webpack.prod.config.js files. But there are some configurations that both files use, so in the spirit of reuse, we also have a webapck.base.config.js to document common configurations.

Webpack basic structure

Webpack configuration is divided into several parts:

  1. Webpack the entry to the package file.
  2. The output of webpack after the file is packaged.
  3. Module configuration (Module) for Webpack when packaging files.
  4. Plugins that Webpack uses to package files.

These four are the basic parts of the WebPack configuration and are ready to be packaged. There are other configurations to be used, which will be mentioned later. If other configurations are not used, please refer to the official documents (3.x official website)/ (I think the translated Chinese documents are better). Let’s first examine some of the configurations shared by the development and build environments. First of all, the entry files are generally the same, right? And then the module configuration is the same when you package, because you’re packing the same files, so the Settings are the same. So we write webpack.base.config.js like this:

var path = require('path');
var root = path.resolve(__dirname, '.. / ');

module.exports = {
    entry: {
        'main': root + '\\app\\index.js',
        jquery:['jquery'],
        ionic:root+'\\app\\assets\\lib\\ionic\\release\\js\\ionic.bundle.min.js',
        datepicker:root+'\\app\\assets\\lib\\ionic-datepicker\\release\\ionic-datepicker.bundle.min.js',
        calendar_pk:root+'\\app\\assets\\lib\\calendar-pk\\release\\js\\calendar_pk.min.js'
    },
    module: {
        loaders: [
            {
                test: /\.(png|jpe? g|gif|woff|svg|eot|ttf)(\? . *)? $/, loader:'url-loader',
                query: {
                    limit: 10000,}}, {test: /\.html$/,
                loader: 'html-loader'
            }

        ]
    },
    resolve: {
        extensions: ['.js'.'.json']}};Copy the code

In fact, there is not only one entry file, I have more than one. As long as the paths are separated correctly. Then there is the module configuration. The idea of Webpack is that all js in a project are modules and then all packaged together. So there’s trouble with some non-JS. But they anticipated this and made a series of loaders to make non-JS files into something webPack could pack. CSS -loader and URL-loader are commonly used. These are used to parse files such as.CSS and image fonts in the project, respectively. As mentioned above, we also use html-loader because there will be more. HTML files to reference in the project. I also have a resolve (resolve) configuration, which is just one item for removing a suffix from a JS reference file. Webpack automatically plus-one item for a.js or.json suffix, saving a bit of suffixes (✧◡✧).

Develop package configuration

Our development package configuration looks like this:

var baseconf = require('./webpack.base.config');
var merge = require('webpack-merge');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var webpack = require('webpack');
var server = require('./configDevServer');
var path = require('path');
var root = path.resolve(__dirname, '.. / ');

var plugins = [
    new webpack.DefinePlugin({
        'process.env': {
            NODE_ENV: JSON.stringify("development")
        }
    }),
    new webpack.optimize.UglifyJsPlugin({
        compress: {
            warnings: false
        }
    }),
    new webpack.ProvidePlugin({
        $: 'jquery',
        jQuery: 'jquery'.'window.jQuery': 'jquery'.'window.$': 'jquery'
    }),
    new webpack.optimize.CommonsChunkPlugin({
        name: 'vendor', // The chunk name of this common code'commons'
        filename: '[name].bundle.js'// The name of the generated file is [name]'commons.bundle.js'With minChunks: 3, // js modules loaded in 4 chunks (i.e., 4 pages) are not included in the common code. I think 3-5 would be appropriate. }), new HtmlWebpackPlugin({ filename:'index.html',
            template: 'index.html',
            inject: true
    }),
    new webpack.HotModuleReplacementPlugin()
];
baseconf.module.loaders.push(
    {
        test: /\.css$/,
        loader: ['style-loader'.'css-loader']}); module.exports = merge(baseconf, { output: { path: root+"/dist",
        publicPath: "/",
        filename: "./js/[name].[chunkhash].js"
    },
    devtool: 'cheap-module-eval-source-map',
    devServer: server,
    plugins: plugins,
});Copy the code

Let’s introduce the basic configuration first. Then write the plugin, after all, we want to develop the configuration to achieve part of the function of the plug-in to do. Webpack.defineplugin is used to let WebPack know that a development environment package is being prepared. Some frameworks recognize development and production environments, and then give warnings and reminders while we’re developing, while in production they block them. Webpack. ProvidePlugin is used when we use JS libraries such as jQuery, the relevant symbols used will be automatically referenced, will not cause errors. Webpack.optimize.Com monsChunkPlugin is used to extract the public in our code use the part of the pack to avoid code duplication, reduce the code size. Webpack. HotModuleReplacementPlugin hot replacement function is used to enable our code, after we change the code development server can update the repack the browser automatically refresh, our changes displayed on the page. HtmlWebpackPlugin is a plugin we installed to automatically insert the generated JS into our HTML template. After writing the plug-in, we also need to write the output. Here specify the output folder and output JS name. Then there’s devtool and dev-server. Devtool means that WebPack makes a map of the packaged files, and if the code goes wrong, it finds it and tells you where to find it. Easy to modify the code. A development server is a local server on which your project resides. With hot replacement, development will be very convenient. Here by simple introduce, development server configuration. / build/configDevServer. Js:

const server={
    contentBase:'/dist/',
    host: 'localhost',// Service host port: 8089,// port inline:true, // Can monitor js changes hot:true// compress:true,
    watchContentBase: true, proxy: {// Set the proxy server for debugging interface'/api':{
            target:'http://www.baidu.com',
            pathRewrite:{"^/api": "/api"}// Override path}}}; module.exports= server;Copy the code

You can see the remarks above to understand the meanings of configuration items. Earlier we installed a Webpack-merge that came into play. As its name suggests, it merges the two WebPack configurations. And then output. So our development environment configuration is written

Production Environment Configuration

Again, configure first:

var baseconf = require('./webpack.base.config');
var path = require('path');
var root = path.resolve(__dirname, '.. / ');
var merge = require('webpack-merge');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var webpack=require('webpack');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var ManifestPlugin = require('webpack-manifest-plugin');
var plugins = [
    new webpack.DefinePlugin({
        'process.env': {
            NODE_ENV:JSON.stringify("development")
        }
    }),
    new webpack.optimize.UglifyJsPlugin({
        compress: {
            warnings: false
        }
    }),
    new HtmlWebpackPlugin({
        filename: 'index.html',
        template: 'index.html',
        inject: true
    }),
    new ExtractTextPlugin({
        filename: './css/[name].css? [contenthash:8]',
        allChunks: true,
    }),
    new webpack.ProvidePlugin({
        $: 'jquery',
        jQuery: 'jquery'.'window.jQuery': 'jquery'.'window.$': 'jquery',
    }),
    new webpack.optimize.CommonsChunkPlugin({
        name: 'commons', // The chunk name of this common code'commons'
        filename: './js/[name].bundle.js', // minChunks: 3,}), new ManifestPlugin(path.join('dist'.'manifest.json'))]; baseconf.module.rules.push( {test: /\.css$/,
        loader: ['style-loader'.'css-loader']}); module.exports=merge(baseconf,{ output: { path: root+"/dist",
        publicPath: ". /",
        filename: "./js/[name].[chunkhash].js"
},
    devtool: false,
    plugins: plugins
});Copy the code

Instead of repeating plugins, let’s talk about a few that aren’t. Webpack. Optimize. UglifyJsPlugin confusion is used to compress javascript code. The ExtractTextPlugin is a separate plugin we installed to separate packaged CSS into a CSS file. When using this plugin, the CSS loader should be set accordingly, so you can see that THE CSS-Loader is not in the public configuration, but in separate. The ManifestPlugin, also installed separately, is used to generate the manifest cache file so that websites can reduce repeated requests for static resources. Also you can see here devtool is set to false, devServer is not set, because it is not required for production, so it is not set.

Let’s run!

Create a js file with the name of the entry specified in the configuration at your entry point to run through webpack. If WebPack doesn’t report any errors, your configuration is basically correct.

Next, I’ll talk about the potholes angular 1.x encounters with webpack packaging. See the next article:

Angular 1.x Project based on WebPack

To see the code in detail, visit my project address github.com/homerious/a…

Please point out any questions or inaccuracies. Thanks for reading!

This article is original, please do not reprint without authorization.