资讯专栏INFORMATION COLUMN

基于webpack构建的angular 1.x 工程(一)webpack篇

Anleb / 1572人阅读

摘要:基于构建的工程一篇现在都已经出到的版本了,可我对它的认识还是停留在的版本。然后是写启动的命令行,也就是上面的这样写的意思是,当你输入你的命令名字就会让执行你对应命令的语句。我们首先把基本的配置引进来。

基于webpack构建的angular 1.x 工程(一)webpack篇

  现在AngularJS都已经出到4.x的版本了,可我对它的认识还是停留在1.x的版本。
  之前用它是为了搭配ionic来写web手机天气 应用(用来应付我大学里一门学科的课设的︿( ̄︶ ̄)︿)。之后就因为它太难学而没有继续深入下去。
  现在就职的公司也有个项目是做混合式的手机app的,居然也是用AngularJS+ionic来做的,而且也是用1.x的版本。
  本来没我什么事的,我这段时间都在用Vuejs。然后上头发现那个项目加载是在太慢了,问我有没有优化的方法。我看了下项目工程结构,发现是用gulp打包的一个工程。可能刚开始做这个项目的时候没掌握好要点,导致整个项目臃肿不堪。gulp我是不会的了,由于一直在用Vuejs,官方cli提供的模板就是用webpack打包的,而且我之前写ReactJS用的也是webpack来打包的。因此,我就用了webpack来重构一下工程。然后写下这篇详细的文章,想给可能会同样遇到的这种问题的朋友做一个参考( • ̀ω•́ )✧。 另外,本文也可以当做webpack的一篇入门文章。

首先,要先配置好工程文件。

  我先列一下我的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"
}

  第一个首先是项目直接用到的依赖,也就是dependencies里的东西
分别有:

 "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"
  }

  我这里的angularangular-cookies都用了具体的版本(就是版本号前面没有用符号^,直接写数字1.4.3),因为不合版本的这两个东西会跟ionic里的angular-ui-router发生冲突导致渲染失败。
  而我这里也没有装ionic,是因为我直接引用的时候会报can"t resolve "ionic"的错误,我也不知道为什么,所以我是直接调用了/app/assets/lib里的ionic.bundle.min.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"
  },

  各种loader是必要的,因为webpack在打包的时候会把你项目里的非js文件转换出来然后打包在一起。我们常用的loader有css-loader,url-loader,这两个分别是解析css和图片的。然后其他的loader我们要看项目需求来按需选取,比如我这里因为是angular 1.x的项目,里面还有挺多的html模板,所以我这里用到了html-loader来解析html。
  其次是webpack——说句题外话,其实webpack一般都是用最新的,因为打包的环境跟所用的框架其实没有太多互相干扰的地方。我一开始想着用的1.x的webpack发现用起来不怎么方便,于是又改回最新的3.x。这也算是个人的一个小小心得吧。然后我们还用了webpack-dev-server。这个是在我们开发的时候用的服务器,可以热替换更新代码。很方便,至于怎么用我后面会详细讲。然后就是webpack-merge这个东西是用来合并webpack配置,这个是在vue项目里看到,感觉还挺好用,就也模仿着用了。最后就是各种插件,extract-text-webpack-plugin这个用来把css样式独立打包成一个css文件的插件,没有它的话,样式只会注入index.html做内联样式;html-webpack-plugin是用于把js注入到index.html里;webpack-manifest-plugin是用来生成网页的manifest文件的。
  然后是写启动webpack的命令行,也就是上面的:

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

这样写的意思是,当你输入npm run + 你的命令名字就会让npm执行你对应命令的语句。比如输入npm run dev,相当于你执行了上面那条dev对应的set NODE_ENV=dev&& webpack-dev-server --config ./build/webpack.dev.config.js"这条语句。这里dev命令执行的是开发版本打包并生成开发的服务器;build命令执行的则是生产版本打包。在打包开发版本的时候,用的是webpack-dev-server,我们让它按照./build/webpack.dev.config.js里的配置(下文会提到)来执行。在打包生产环境,是直接运行webpack,让它按照./build/webpack.prod.config.js里的配置来执行。

  关于这份package.json里其他的配置有问题的可以在评论里提哈~~

然后来写webpack的配置文件 概述

  安装了webpack,我们要配置好,让它按照我们的期望来工作。
一般我们都会用 webpack.config.js来命名webpack的配置文件,以免和其他配置文件搞混。但是由于我们一般都会分开开发环境和生产环境,而对于这个两个环境打包我们要求会有点不一样。开发环境我们希望它可以直接模仿生产环境放上服务器测试;
然后又想它可以一有改动就会自动打包更新显示在页面,不用我们手动刷新浏览器;
不希望它打包花的时间太长;如果出错会有相应的提示等等。而生产环境我们想尽量压缩文件大小,生成manifest文件等等。因此,我们就需要把开发打包和生产打包的配置分开来。这里我们就分开了 webpack.dev.config.jswebpack.prod.config.js两个文件。但是还是有些配置是两个文件都会用到的,本着复用的精神,所以我们还有一个 webapck.base.config.js来记录公共的配置。

webpack基本结构

  webpack的配置主要分为几个部分:

webpack打包文件的入口(entry)。

webpack打包完文件后输出的出口(output)。

webpack在打包文件时的模块配置(module)。

webpack在打包文件时用到的插件(plugin)。

  这四个是webpack配置的基本部分,写好了这四个基本可以打包成功了。
还有其他要用的配置后面会说到,其他配置没用到的可以看一下官方的文档(3.x的官网)/ (个人觉得翻译的比较好的中文文档)。接下来我们先来分析下开发环境和生成环境共用的部分配置。首先入口文件一般都是一样的吧?然后打包时模块配置也是一样的,因为你打包时的文件都是一样的,所以设置也是一样的。所以我们webpack.base.config.js是这样写的:

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

module.exports = {
    entry: {
        "main": root + "appindex.js",
        jquery:["jquery"],
        ionic:root+"appassetslibionic
eleasejsionic.bundle.min.js",
        datepicker:root+"appassetslibionic-datepicker
eleaseionic-datepicker.bundle.min.js",
        calendar_pk:root+"appassetslibcalendar-pk
eleasejscalendar_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"]
    }

};

  入口(entry)文件其实不一定是只有一个,我这里就有多个。只要路径分开写正确就可以了。
  然后是模块(module)配置,webpack的思想是把工程所有的js都是模块,然后全部打包在一起。所以遇到一些非js会有麻烦。但是他们早就预料这种情况,做出了一些系列的loader(加载器)来把一些非js文件做成webpack能打包的东西。
一般都会用到的是css-loader, url-loader。这两个分别用来解析项目里.css和图片字体之类的文件。上面说过,由于项目中会有较多的.html文件要引用,所以我们还用了 html-loader。我这里还有一个 resolve(解析)的配置,这个是用来js里引用文件的时候,不写后缀的话,webpack就会自动为其加上.js或.json的后缀,可以省一些写后缀的时间(✧◡✧)。

开发打包配置

  我们的开发打包配置是这样的:

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", // 这公共代码的chunk名为"commons"
        filename: "[name].bundle.js", // 生成后的文件名,虽说用了[name],但实际上就是"commons.bundle.js"了
        minChunks: 3, // 设定要有4个chunk(即4个页面)加载的js模块才会被纳入公共代码。这数目自己考虑吧,我认为3-5比较合适。
    }),
    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,
});

  我们首先把基本的配置引进来。然后写插件(plugin),毕竟我们开发配置想实现的功能有部分需要插件来做。
webpack.DefinePlugin是用来让webpack知道正在准备的是开发环境打包。某些框架会识别开发和生产环境,然后在我们开发的时候会给出相应的警告和提示,而在生产环境则会屏蔽这些内容。webpack.ProvidePlugin是当我们用到 jQuery之类的js库的时候,用到的相关符号都会自动进行引用,不会导致报错。webpack.optimize.CommonsChunkPlugin是用来提取我们代码里的公共用到的部分,避免代码重复打包,减少代码体积。webpack.HotModuleReplacementPlugin是用来启用我们的代码热替换功能,在我们改了代码之后开发服务器可以重新打包更新,浏览器自动刷新,把我们的改动显示在页面。HtmlWebpackPlugin是我们自己安装的插件,用来把生成的js自动插入到我们的html模板里面。
  写完了插件之后,我们还要写输出(output)。这里指定下输出文件夹和输出的js名字即可。然后是是开发工具(devtool)和开发服务器(dev-server),开发工具的意思是,webpack会根据打包的文件做出一个标识的map文件,如果代码出错的话,它会找出来,然后提示在什么地方。方便修改代码。开发服务器是一个建立在本地的服务器,上面就是你的项目。搭配热替换功能,开发会很方便。这里顺带简单介绍下,开发服务器配置 ./build/configDevServer.js

const server={
    contentBase:"/dist/",
    host: "localhost",//服务主机
    port: 8089,//端口
    inline: true, // 可以监控js变化
    hot: true, // 热启动
    compress: true,
    watchContentBase: true,
    proxy: {//设置代理服务器,用于调试接口
        "/api":{
            target:"http://www.baidu.com",
            pathRewrite:{"^/api": "/api"}//重写路径
        }
    }
};
module.exports= server;

  可以看上面的备注来理解对应的配置项的意思。
  上文我们装了个 webpack-merge这时就发挥作用了。正如它的名字一样,它会把两个webpack配置合并起来。然后输出。这样我们的开发环境配置写好了

生产环境配置

  同样,先上配置:

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", // 这公共代码的chunk名为"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
});

  重复的插件我们就不说了,我们说说几个上面没有的插件。 webpack.optimize.UglifyJsPlugin是用来压缩混淆js代码的。ExtractTextPlugin是我们另外安装的,用来把打包的css独立出来成一个css文件。使用这个插件的时候,css的loader要相应做一下设置,所以可以看到 css-loader我没有放到公共配置,里面而是分开了。ManifestPlugin也是另外安装的,用来生成manifest缓存文件,使网站可以减少对静态资源的重复请求。另外你可以发现这里devtool设成了false,没有设置devserver,因为不是生产所需要的,所以没有设置。

来跑一遍吧!

在你的入口的地方建立一个配置里的entry规定名字的js文件,就可以先跑一遍webpack。
如果webpack没有报错,就说明你的配置基本是对的。

接下来,我会就angular 1.x 用webpack打包打包遇到的坑来说一说,请看下一篇文章:

基于webpack构建的angular 1.x工程(angular篇)

想看详细代码,可以访问我的项目地址
https://github.com/homerious/angular-ionic-webpack

有什么问题或者不对的地方欢迎指出,谢谢阅读!

本文原创,未经授权请勿转载。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/89440.html

相关文章

  • 基于webpack构建angular 1.x工程angular

    摘要:基于构建的工程篇上一篇基于构建的工程一篇里我们已经成功构建了整个项目的打包配置。不同的模块之间都会有标识来标志,所以不会说存在干扰和污染的问题。但是对于我这个重构的项目,就会有麻烦要改写的文件有太多了。然而还有一种情况。 基于webpack构建的angular 1.x工程(angular篇)   上一篇基于webpack构建的angular 1.x 工程(一)webpack篇里我们已经...

    jerry 评论0 收藏0
  • 前端每周清单半年盘点之 Angular

    摘要:延伸阅读学习与实践资料索引与前端工程化实践前端每周清单半年盘点之篇前端每周清单半年盘点之与篇前端每周清单半年盘点之篇 前端每周清单专注前端领域内容,以对外文资料的搜集为主,帮助开发者了解一周前端热点;分为新闻热点、开发教程、工程实践、深度阅读、开源项目、巅峰人生等栏目。欢迎关注【前端之巅】微信公众号(ID:frontshow),及时获取前端每周清单;本文则是对于半年来发布的前端每周清单...

    LeviDing 评论0 收藏0
  • Angular 1.x 跟上时代步伐

    摘要:所以说的模块机制没有解决文件依赖关系和文件异步加载的问题。大部分团队还是停留在第二第三阶段,每个阶段的实现都有很多种选择。希望这篇文章能够激起大家永远保持积极向前追求完美代码的心,不仅对自己的成长也会对公司带来无限的价值。 本篇技术博客来自有着化腐朽为神奇能力的,Worktile 技术牛人Web 总监 @徐海峰 大神的分享~满满的干货,你值得拥有! Worktile 的前端构建之路 2...

    李增田 评论0 收藏0
  • 7月份前端资源分享

    摘要:更多资源请文章转自月份前端资源分享的作用数组元素随机化排序算法实现学习笔记数组随机排序个变态题解析上个变态题解析下中的数字前端开发笔记本过目不忘正则表达式聊一聊前端存储那些事儿一键分享到各种写给刚入门的前端工程师的前后端交互指南物联网世界的 更多资源请Star:https://github.com/maidishike... 文章转自:https://github.com/jsfr...

    pingan8787 评论0 收藏0

发表评论

0条评论

Anleb

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<